[IMP] types: make component generic types optional

In most cases, we just want Component<any, Env>. But since it was so
annoying to have always the type Env, we actually used
Component<any,any> everywhere.

With this commit, the generic types have a default (and their order is
swapped), so we can simply use Component in most cases, and
Component<Props> when we want to type the props.
This commit is contained in:
Géry Debongnie
2020-02-05 21:30:14 +01:00
committed by aab-odoo
parent d212309f1b
commit 3fdc7a48f3
33 changed files with 700 additions and 711 deletions
-1
View File
@@ -41,4 +41,3 @@ Each component has an internal `id`, which is very useful when debugging.
Note that it is certainly useful to run this code at some point in an application, Note that it is certainly useful to run this code at some point in an application,
just to get a feel of what each user action implies, for the framework. just to get a feel of what each user action implies, for the framework.
+4 -2
View File
@@ -1,6 +1,5 @@
# 🦉 Quick Overview 🦉 # 🦉 Quick Overview 🦉
Owl components in an application are used to define a (dynamic) tree of components. Owl components in an application are used to define a (dynamic) tree of components.
``` ```
@@ -110,7 +109,10 @@ class Parent extends Component {
line="line" /> line="line" />
</div>`; </div>`;
static components = { OrderLine }; static components = { OrderLine };
orders = useState([{ id: 1, name: "Coffee", quantity: 0 }, { id: 2, name: "Tea", quantity: 0 }]); orders = useState([
{ id: 1, name: "Coffee", quantity: 0 },
{ id: 2, name: "Tea", quantity: 0 }
]);
addToOrder(event) { addToOrder(event) {
const line = event.detail.line; const line = event.detail.line;
+15 -29
View File
@@ -9,16 +9,16 @@
## Overview ## Overview
Each software project has its specific needs. Many of these needs can be solved Each software project has its specific needs. Many of these needs can be solved
with some tooling: `webpack`, `gulp`, css preprocessor, bundlers, transpilers, ... with some tooling: `webpack`, `gulp`, css preprocessor, bundlers, transpilers, ...
Because of that, it is usually not simple to just start a project. Some Because of that, it is usually not simple to just start a project. Some
frameworks provide their own tooling to help with that. But then, you have to frameworks provide their own tooling to help with that. But then, you have to
integrate and learn how these applications work. integrate and learn how these applications work.
Owl is designed to be used with no tooling at all. Because of that, Owl can Owl is designed to be used with no tooling at all. Because of that, Owl can
"easily" be integrated in a modern build toolchain. In this section, we will "easily" be integrated in a modern build toolchain. In this section, we will
discuss a few different setups to start a project. Each of these setups has discuss a few different setups to start a project. Each of these setups has
advantages and disadvantages in different situations. advantages and disadvantages in different situations.
## Simple html file ## Simple html file
@@ -74,8 +74,7 @@ whenReady(setup);
Now, simply loading this html file in a browser should display a welcome message. Now, simply loading this html file in a browser should display a welcome message.
This setup is not fancy, but it is extremely simple. There are no tooling at This setup is not fancy, but it is extremely simple. There are no tooling at
all required. It can be slightly optimized by using the minified build of Owl. all required. It can be slightly optimized by using the minified build of Owl.
## With a static server ## With a static server
@@ -87,7 +86,7 @@ variables and we lose autocompletion across files.
There is a low tech solution to this issue: using native javascript modules. There is a low tech solution to this issue: using native javascript modules.
This however has a requirement: for security reasons, browsers will not accept This however has a requirement: for security reasons, browsers will not accept
modules on content served through the `file` protocol. This means that we need modules on content served through the `file` protocol. This means that we need
to use a static server. to use a static server.
Let us start a new project with the following file structure: Let us start a new project with the following file structure:
@@ -101,7 +100,6 @@ hello_owl/
owl.js owl.js
``` ```
As previously, the file `owl.js` can be downloaded from the last release published at As previously, the file `owl.js` can be downloaded from the last release published at
[https://github.com/odoo/owl/releases](https://github.com/odoo/owl/releases). [https://github.com/odoo/owl/releases](https://github.com/odoo/owl/releases).
@@ -130,10 +128,9 @@ const { Component } = owl;
const { xml } = owl.tags; const { xml } = owl.tags;
export class App extends Component { export class App extends Component {
static template = xml`<div>Hello Owl</div>`; static template = xml`<div>Hello Owl</div>`;
} }
// main.js --------------------------------------------------------------------- // main.js ---------------------------------------------------------------------
import { App } from "./app.js"; import { App } from "./app.js";
@@ -145,11 +142,11 @@ function setup() {
owl.utils.whenReady(setup); owl.utils.whenReady(setup);
``` ```
The `main.js` file import the `app.js` file. Note that the import statement has The `main.js` file import the `app.js` file. Note that the import statement has
a `.js` suffix, which is important. Most text editor can understand this syntax a `.js` suffix, which is important. Most text editor can understand this syntax
and will provide autocompletion. and will provide autocompletion.
Now, to execute this code, we need to serve the `src` folder statically. A low Now, to execute this code, we need to serve the `src` folder statically. A low
tech way to do that is to use for example the python `SimpleHTTPServer` feature: tech way to do that is to use for example the python `SimpleHTTPServer` feature:
``` ```
@@ -180,18 +177,16 @@ that, we can add the following `package.json` file at the root of the project:
We can now install the `serve` tool with the command `npm install`, and then, We can now install the `serve` tool with the command `npm install`, and then,
start a static server with the simple `npm run serve` command. start a static server with the simple `npm run serve` command.
## Standard Javascript project ## Standard Javascript project
The previous setup works, and is certainly good for some usecases, including The previous setup works, and is certainly good for some usecases, including
quick prototyping. However, it lacks some useful features, such as livereload, quick prototyping. However, it lacks some useful features, such as livereload,
a test suite, or bundling the code in a single file. a test suite, or bundling the code in a single file.
Each of these features, and many others, can be done in many different ways. Each of these features, and many others, can be done in many different ways.
Since it is really not trivial to configure such a project, we provide here an Since it is really not trivial to configure such a project, we provide here an
example that can be used as a starting point. example that can be used as a starting point.
Our standard Owl project has the following file structure: Our standard Owl project has the following file structure:
``` ```
@@ -244,7 +239,6 @@ export class App extends Component {
} }
} }
// src/main.js ----------------------------------------------------------------- // src/main.js -----------------------------------------------------------------
import { utils } from "@odoo/owl"; import { utils } from "@odoo/owl";
import { App } from "./components/App"; import { App } from "./components/App";
@@ -256,7 +250,6 @@ function setup() {
utils.whenReady(setup); utils.whenReady(setup);
// tests/components/App.test.js ------------------------------------------------ // tests/components/App.test.js ------------------------------------------------
import { App } from "../../src/components/App"; import { App } from "../../src/components/App";
import { makeTestFixture, nextTick, click } from "../helpers"; import { makeTestFixture, nextTick, click } from "../helpers";
@@ -283,16 +276,13 @@ describe("App", () => {
}); });
}); });
// tests/helpers.js ------------------------------------------------------------ // tests/helpers.js ------------------------------------------------------------
import { Component } from "@odoo/owl"; import { Component } from "@odoo/owl";
import "regenerator-runtime/runtime"; import "regenerator-runtime/runtime";
export async function nextTick() { export async function nextTick() {
return new Promise(function(resolve) { return new Promise(function(resolve) {
setTimeout(() => setTimeout(() => Component.scheduler.requestAnimationFrame(() => resolve()));
Component.scheduler.requestAnimationFrame(() => resolve())
);
}); });
} }
@@ -347,9 +337,7 @@ dist/
"@odoo/owl": "^1.0.4" "@odoo/owl": "^1.0.4"
}, },
"babel": { "babel": {
"plugins": [ "plugins": ["@babel/plugin-proposal-class-properties"],
"@babel/plugin-proposal-class-properties"
],
"env": { "env": {
"test": { "test": {
"plugins": ["transform-es2015-modules-commonjs"] "plugins": ["transform-es2015-modules-commonjs"]
@@ -359,9 +347,7 @@ dist/
"jest": { "jest": {
"verbose": false, "verbose": false,
"testRegex": "(/tests/.*(test|spec))\\.js?$", "testRegex": "(/tests/.*(test|spec))\\.js?$",
"moduleFileExtensions": [ "moduleFileExtensions": ["js"],
"js"
],
"transform": { "transform": {
"^.+\\.[t|j]sx?$": "babel-jest" "^.+\\.[t|j]sx?$": "babel-jest"
} }
-2
View File
@@ -46,9 +46,7 @@ which cannot be considered either a tutorial, or reference documentation.
- [Comparison with React/Vue](miscellaneous/comparison.md) - [Comparison with React/Vue](miscellaneous/comparison.md)
- [Why did Odoo built Owl?](miscellaneous/why_owl.md) - [Why did Odoo built Owl?](miscellaneous/why_owl.md)
--- ---
Found an issue in the documentation? A broken link? Some outdated information? Found an issue in the documentation? A broken link? Some outdated information?
Please open an issue or submit a PR! Please open an issue or submit a PR!
+10 -10
View File
@@ -46,7 +46,7 @@ interface MountOptions {
* useful to typecheck and describe the internal keys used by Owl to manage the * useful to typecheck and describe the internal keys used by Owl to manage the
* component tree. * component tree.
*/ */
interface Internal<T extends Env, Props> { interface Internal<T extends Env> {
// each component has a unique id, useful mostly to handle parent/child // each component has a unique id, useful mostly to handle parent/child
// relationships // relationships
readonly id: number; readonly id: number;
@@ -58,8 +58,8 @@ interface Internal<T extends Env, Props> {
// parent and children keys are obviously useful to setup the parent-children // parent and children keys are obviously useful to setup the parent-children
// relationship. // relationship.
parent: Component<T, any> | null; parent: Component<any, T> | null;
children: { [key: number]: Component<T, any> }; children: { [key: number]: Component<any, T> };
// children mapping: from templateID to componentID. templateID identifies a // children mapping: from templateID to componentID. templateID identifies a
// place in a template. The t-component directive needs it to be able to get // place in a template. The t-component directive needs it to be able to get
// the component instance back whenever the template is rerendered. // the component instance back whenever the template is rerendered.
@@ -85,7 +85,7 @@ interface Internal<T extends Env, Props> {
willStartCB: Function | null; willStartCB: Function | null;
willUpdatePropsCB: Function | null; willUpdatePropsCB: Function | null;
classObj: { [key: string]: boolean } | null; classObj: { [key: string]: boolean } | null;
refs: { [key: string]: Component<T, any> | HTMLElement | undefined } | null; refs: { [key: string]: Component<any, T> | HTMLElement | undefined } | null;
} }
export const portalSymbol = Symbol("portal"); // FIXME export const portalSymbol = Symbol("portal"); // FIXME
@@ -95,11 +95,11 @@ export const portalSymbol = Symbol("portal"); // FIXME
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
let nextId = 1; let nextId = 1;
export class Component<T extends Env, Props extends {}> { export class Component<Props extends {} = any, T extends Env = Env> {
readonly __owl__: Internal<Env, Props>; readonly __owl__: Internal<T>;
static template?: string | null = null; static template?: string | null = null;
static _template?: string | null = null; static _template?: string | null = null;
static current: Component<any, any> | null = null; static current: Component | null = null;
static components = {}; static components = {};
static props?: any; static props?: any;
static defaultProps?: any; static defaultProps?: any;
@@ -130,7 +130,7 @@ export class Component<T extends Env, Props extends {}> {
* hand. Other components should be created automatically by the framework (with * hand. Other components should be created automatically by the framework (with
* the t-component directive in a template) * the t-component directive in a template)
*/ */
constructor(parent?: Component<T, any> | null, props?: Props) { constructor(parent?: Component<any, T> | null, props?: Props) {
Component.current = this; Component.current = this;
let constr = this.constructor as any; let constr = this.constructor as any;
@@ -441,7 +441,7 @@ export class Component<T extends Env, Props extends {}> {
* Note that it does not call the __callWillUnmount method to avoid visiting * Note that it does not call the __callWillUnmount method to avoid visiting
* all children many times. * all children many times.
*/ */
__destroy(parent: Component<any, any> | null) { __destroy(parent: Component | null) {
const __owl__ = this.__owl__; const __owl__ = this.__owl__;
const isMounted = __owl__.isMounted; const isMounted = __owl__.isMounted;
if (isMounted) { if (isMounted) {
@@ -501,7 +501,7 @@ export class Component<T extends Env, Props extends {}> {
* Private trigger method, allows to choose the component which triggered * Private trigger method, allows to choose the component which triggered
* the event in the first place * the event in the first place
*/ */
__trigger(component: Component<any, any>, eventType: string, payload?: any) { __trigger(component: Component, eventType: string, payload?: any) {
if (this.el) { if (this.el) {
const ev = new OwlEvent(component, eventType, { const ev = new OwlEvent(component, eventType, {
bubbles: true, bubbles: true,
+2 -2
View File
@@ -50,7 +50,7 @@ export class Fiber {
scope: any; scope: any;
component: Component<any, any>; component: Component;
vnode: VNode | null = null; vnode: VNode | null = null;
root: Fiber; root: Fiber;
@@ -61,7 +61,7 @@ export class Fiber {
error?: Error; error?: Error;
constructor(parent: Fiber | null, component: Component<any, any>, force, inserter) { constructor(parent: Fiber | null, component: Component, force: boolean, inserter) {
this.component = component; this.component = component;
this.force = force; this.force = force;
this.inserter = inserter; this.inserter = inserter;
+2 -2
View File
@@ -100,11 +100,11 @@ export class Context extends EventBus {
* to context state changes. The `useContext` method returns the context state * to context state changes. The `useContext` method returns the context state
*/ */
export function useContext(ctx: Context): any { export function useContext(ctx: Context): any {
const component: Component<any, any> = Component.current!; const component: Component = Component.current!;
return useContextWithCB(ctx, component, component.render.bind(component)); return useContextWithCB(ctx, component, component.render.bind(component));
} }
export function useContextWithCB(ctx: Context, component: Component<any, any>, method): any { export function useContextWithCB(ctx: Context, component: Component, method): any {
const __owl__ = component.__owl__; const __owl__ = component.__owl__;
const id = __owl__.id; const id = __owl__.id;
const mapping = ctx.mapping; const mapping = ctx.mapping;
+1 -1
View File
@@ -7,7 +7,7 @@ import { Component } from "../component/component";
*/ */
export class OwlEvent<T> extends CustomEvent<T> { export class OwlEvent<T> extends CustomEvent<T> {
originalComponent: Component<any, any>; originalComponent: Component;
constructor(component, eventType, options) { constructor(component, eventType, options) {
super(eventType, options); super(eventType, options);
this.originalComponent = component; this.originalComponent = component;
+6 -6
View File
@@ -22,7 +22,7 @@ import { Observer } from "./core/observer";
* trigger a rerendering of the current component. * trigger a rerendering of the current component.
*/ */
export function useState<T>(state: T): T { export function useState<T>(state: T): T {
const component: Component<any, any> = Component.current!; const component: Component = Component.current!;
const __owl__ = component.__owl__; const __owl__ = component.__owl__;
if (!__owl__.observer) { if (!__owl__.observer) {
__owl__.observer = new Observer(); __owl__.observer = new Observer();
@@ -37,7 +37,7 @@ export function useState<T>(state: T): T {
function makeLifecycleHook(method: string, reverse: boolean = false) { function makeLifecycleHook(method: string, reverse: boolean = false) {
if (reverse) { if (reverse) {
return function(cb) { return function(cb) {
const component: Component<any, any> = Component.current!; const component: Component = Component.current!;
if (component.__owl__[method]) { if (component.__owl__[method]) {
const current = component.__owl__[method]; const current = component.__owl__[method];
component.__owl__[method] = function() { component.__owl__[method] = function() {
@@ -50,7 +50,7 @@ function makeLifecycleHook(method: string, reverse: boolean = false) {
}; };
} else { } else {
return function(cb) { return function(cb) {
const component: Component<any, any> = Component.current!; const component: Component = Component.current!;
if (component.__owl__[method]) { if (component.__owl__[method]) {
const current = component.__owl__[method]; const current = component.__owl__[method];
component.__owl__[method] = function() { component.__owl__[method] = function() {
@@ -66,7 +66,7 @@ function makeLifecycleHook(method: string, reverse: boolean = false) {
function makeAsyncHook(method: string) { function makeAsyncHook(method: string) {
return function(cb) { return function(cb) {
const component: Component<any, any> = Component.current!; const component: Component = Component.current!;
if (component.__owl__[method]) { if (component.__owl__[method]) {
const current = component.__owl__[method]; const current = component.__owl__[method];
component.__owl__[method] = function(...args) { component.__owl__[method] = function(...args) {
@@ -96,7 +96,7 @@ export const onWillUpdateProps = makeAsyncHook("willUpdatePropsCB");
*/ */
interface Ref { interface Ref {
el: HTMLElement | null; el: HTMLElement | null;
comp: Component<any, any> | null; comp: Component | null;
} }
export function useRef(name: string): Ref { export function useRef(name: string): Ref {
@@ -111,7 +111,7 @@ export function useRef(name: string): Ref {
} }
return null; return null;
}, },
get comp(): Component<any, any> | null { get comp(): Component | null {
const val = __owl__.refs && __owl__.refs[name]; const val = __owl__.refs && __owl__.refs[name];
return val instanceof Component ? val : null; return val instanceof Component ? val : null;
} }
+1 -1
View File
@@ -10,7 +10,7 @@ import { xml } from "../tags";
* from this coordination. This is the goal of the AsyncRoot component. * from this coordination. This is the goal of the AsyncRoot component.
*/ */
export class AsyncRoot extends Component<any, any> { export class AsyncRoot extends Component {
static template = xml`<t t-slot="default"/>`; static template = xml`<t t-slot="default"/>`;
async __updateProps(nextProps, parentFiber) { async __updateProps(nextProps, parentFiber) {
+7 -3
View File
@@ -18,7 +18,11 @@ import { useSubEnv } from "../hooks";
* are re-triggered on an empty <portal> node located in the parent's DOM. * are re-triggered on an empty <portal> node located in the parent's DOM.
*/ */
export class Portal extends Component<any, any> { interface Props {
target: string;
}
export class Portal extends Component<Props> {
static template = xml`<portal><t t-slot="default"/></portal>`; static template = xml`<portal><t t-slot="default"/></portal>`;
static props = { static props = {
target: { target: {
@@ -43,7 +47,7 @@ export class Portal extends Component<any, any> {
// represents the element that is moved somewhere else // represents the element that is moved somewhere else
portal: VNode | null = null; portal: VNode | null = null;
// the target where we will move `portal` // the target where we will move `portal`
target: HTMLElement | null = null; target: Element | null = null;
constructor(parent, props) { constructor(parent, props) {
super(parent, props); super(parent, props);
@@ -158,7 +162,7 @@ export class Portal extends Component<any, any> {
/** /**
* Override to set the env * Override to set the env
*/ */
__trigger(component: Component<any, any>, eventType: string, payload?: any) { __trigger(component: Component, eventType: string, payload?: any) {
const env = this.env; const env = this.env;
this.env = this.parentEnv; this.env = this.parentEnv;
super.__trigger(component, eventType, payload); super.__trigger(component, eventType, payload);
+1 -1
View File
@@ -4,7 +4,7 @@ import { Destination, RouterEnv } from "./router";
type Props = Destination; type Props = Destination;
export class Link<Env extends RouterEnv> extends Component<Env, Props> { export class Link<Env extends RouterEnv> extends Component<Props, Env> {
static template = xml` static template = xml`
<a t-att-class="{'router-link-active': isActive }" <a t-att-class="{'router-link-active': isActive }"
t-att-href="href" t-att-href="href"
+1 -1
View File
@@ -1,7 +1,7 @@
import { Component } from "../component/component"; import { Component } from "../component/component";
import { xml } from "../tags"; import { xml } from "../tags";
export class RouteComponent extends Component<any, {}> { export class RouteComponent extends Component {
static template = xml` static template = xml`
<t> <t>
<t <t
+1 -1
View File
@@ -83,7 +83,7 @@ interface SelectorOptions {
const isStrictEqual = (a, b) => a === b; const isStrictEqual = (a, b) => a === b;
export function useStore(selector, options: SelectorOptions = {}): any { export function useStore(selector, options: SelectorOptions = {}): any {
const component: Component<any, any> = Component.current!; const component: Component = Component.current!;
const componentId = component.__owl__.id; const componentId = component.__owl__.id;
const store = options.store || (component.env.store as Store); const store = options.store || (component.env.store as Store);
if (!(store instanceof Store)) { if (!(store instanceof Store)) {
+66 -66
View File
@@ -25,7 +25,7 @@ afterEach(() => {
fixture.remove(); fixture.remove();
}); });
function children(w: Component<any, any>): Component<any, any>[] { function children(w: Component): Component[] {
const childrenMap = w.__owl__.children; const childrenMap = w.__owl__.children;
return Object.keys(childrenMap).map(id => childrenMap[id]); return Object.keys(childrenMap).map(id => childrenMap[id]);
} }
@@ -33,7 +33,7 @@ function children(w: Component<any, any>): Component<any, any>[] {
describe("async rendering", () => { describe("async rendering", () => {
test("destroying a widget before start is over", async () => { test("destroying a widget before start is over", async () => {
let def = makeDeferred(); let def = makeDeferred();
class W extends Component<any, any> { class W extends Component {
static template = xml`<div/>`; static template = xml`<div/>`;
willStart(): Promise<void> { willStart(): Promise<void> {
return def; return def;
@@ -53,7 +53,7 @@ describe("async rendering", () => {
test("destroying/recreating a subwidget with different props (if start is not over)", async () => { test("destroying/recreating a subwidget with different props (if start is not over)", async () => {
let def = makeDeferred(); let def = makeDeferred();
let n = 0; let n = 0;
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span>child:<t t-esc="props.val"/></span>`; static template = xml`<span>child:<t t-esc="props.val"/></span>`;
constructor(parent, props) { constructor(parent, props) {
super(parent, props); super(parent, props);
@@ -63,7 +63,7 @@ describe("async rendering", () => {
return def; return def;
} }
} }
class W extends Component<any, any> { class W extends Component {
static template = xml`<div><t t-if="state.val > 1"><Child val="state.val"/></t></div>`; static template = xml`<div><t t-if="state.val > 1"><Child val="state.val"/></t></div>`;
static components = { Child }; static components = { Child };
state = useState({ val: 1 }); state = useState({ val: 1 });
@@ -90,7 +90,7 @@ describe("async rendering", () => {
let defB = makeDeferred(); let defB = makeDeferred();
let nbRenderings: number = 0; let nbRenderings: number = 0;
class ChildA extends Component<any, any> { class ChildA extends Component {
static template = xml`<span><t t-esc="getValue()"/></span>`; static template = xml`<span><t t-esc="getValue()"/></span>`;
willStart(): Promise<void> { willStart(): Promise<void> {
return defA; return defA;
@@ -101,13 +101,13 @@ describe("async rendering", () => {
} }
} }
class ChildB extends Component<any, any> { class ChildB extends Component {
static template = xml`<span>b</span>`; static template = xml`<span>b</span>`;
willStart(): Promise<void> { willStart(): Promise<void> {
return defB; return defB;
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml` static template = xml`
<div> <div>
<t t-if="state.flagA"><ChildA /></t> <t t-if="state.flagA"><ChildA /></t>
@@ -139,20 +139,20 @@ describe("async rendering", () => {
let defA = makeDeferred(); let defA = makeDeferred();
let defB = makeDeferred(); let defB = makeDeferred();
class ChildA extends Component<any, any> { class ChildA extends Component {
static template = xml`<span>a<t t-esc="props.val"/></span>`; static template = xml`<span>a<t t-esc="props.val"/></span>`;
willUpdateProps(): Promise<void> { willUpdateProps(): Promise<void> {
return defA; return defA;
} }
} }
class ChildB extends Component<any, any> { class ChildB extends Component {
static template = xml`<span>b<t t-esc="props.val"/></span>`; static template = xml`<span>b<t t-esc="props.val"/></span>`;
willStart(): Promise<void> { willStart(): Promise<void> {
return defB; return defB;
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml` static template = xml`
<div> <div>
<ChildA val="state.valA"/> <ChildA val="state.valA"/>
@@ -182,20 +182,20 @@ describe("async rendering", () => {
let defA = makeDeferred(); let defA = makeDeferred();
let defB = makeDeferred(); let defB = makeDeferred();
class ChildA extends Component<any, any> { class ChildA extends Component {
static template = xml`<span>a<t t-esc="props.val"/></span>`; static template = xml`<span>a<t t-esc="props.val"/></span>`;
willUpdateProps(): Promise<void> { willUpdateProps(): Promise<void> {
return defA; return defA;
} }
} }
class ChildB extends Component<any, any> { class ChildB extends Component {
static template = xml`<span>b<t t-esc="props.val"/></span>`; static template = xml`<span>b<t t-esc="props.val"/></span>`;
willStart(): Promise<void> { willStart(): Promise<void> {
return defB; return defB;
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml` static template = xml`
<div> <div>
<ChildA val="state.valA"/> <ChildA val="state.valA"/>
@@ -224,7 +224,7 @@ describe("async rendering", () => {
const steps: string[] = []; const steps: string[] = [];
const defs = [makeDeferred(), makeDeferred()]; const defs = [makeDeferred(), makeDeferred()];
let index = 0; let index = 0;
class ChildA extends Component<any, any> { class ChildA extends Component {
static template = xml`<span><t t-esc="props.val"/></span>`; static template = xml`<span><t t-esc="props.val"/></span>`;
willUpdateProps(): Promise<void> { willUpdateProps(): Promise<void> {
return defs[index++]; return defs[index++];
@@ -234,7 +234,7 @@ describe("async rendering", () => {
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><ChildA val="state.valA"/></div>`; static template = xml`<div><ChildA val="state.valA"/></div>`;
static components = { ChildA }; static components = { ChildA };
state = useState({ valA: 1 }); state = useState({ valA: 1 });
@@ -258,7 +258,7 @@ describe("async rendering", () => {
test("update a sub-component twice in the same frame, 2", async () => { test("update a sub-component twice in the same frame, 2", async () => {
const steps: string[] = []; const steps: string[] = [];
class ChildA extends Component<any, any> { class ChildA extends Component {
static template = xml`<span><t t-esc="val()"/></span>`; static template = xml`<span><t t-esc="val()"/></span>`;
patched() { patched() {
steps.push("patched"); steps.push("patched");
@@ -269,7 +269,7 @@ describe("async rendering", () => {
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><ChildA val="state.valA"/></div>`; static template = xml`<div><ChildA val="state.valA"/></div>`;
static components = { ChildA }; static components = { ChildA };
state = useState({ valA: 1 }); state = useState({ valA: 1 });
@@ -302,9 +302,9 @@ describe("async rendering", () => {
}); });
test("components in a node in a t-foreach ", async () => { test("components in a node in a t-foreach ", async () => {
class Child extends Component<any, any> {} class Child extends Component {}
class App extends Component<any, any> { class App extends Component {
static components = { Child }; static components = { Child };
get items() { get items() {
@@ -335,7 +335,7 @@ describe("async rendering", () => {
test("properly behave when destroyed/unmounted while rendering ", async () => { test("properly behave when destroyed/unmounted while rendering ", async () => {
const def = makeDeferred(); const def = makeDeferred();
class SubChild extends Component<any, any> { class SubChild extends Component {
static template = xml`<div/>`; static template = xml`<div/>`;
willPatch() { willPatch() {
throw new Error("Should not happen!"); throw new Error("Should not happen!");
@@ -348,12 +348,12 @@ describe("async rendering", () => {
} }
} }
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<div><SubChild /></div>`; static template = xml`<div><SubChild /></div>`;
static components = { SubChild }; static components = { SubChild };
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><t t-if="state.flag"><Child val="state.val"/></t></div>`; static template = xml`<div><t t-if="state.flag"><Child val="state.val"/></t></div>`;
static components = { Child }; static components = { Child };
state = useState({ flag: true, val: "Framboise Lindemans" }); state = useState({ flag: true, val: "Framboise Lindemans" });
@@ -396,18 +396,18 @@ describe("async rendering", () => {
`); `);
let destroyCount = 0; let destroyCount = 0;
class ChildA extends Component<any, any> { class ChildA extends Component {
destroy() { destroy() {
destroyCount++; destroyCount++;
super.destroy(); super.destroy();
} }
} }
class ChildB extends Component<any, any> { class ChildB extends Component {
willStart(): any { willStart(): any {
return new Promise(function() {}); return new Promise(function() {});
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { ChildA, ChildB }; static components = { ChildA, ChildB };
state = useState({ valA: 1, valB: 2, flag: false }); state = useState({ valA: 1, valB: 2, flag: false });
} }
@@ -426,11 +426,11 @@ describe("async rendering", () => {
}); });
test("rendering component again in next microtick", async () => { test("rendering component again in next microtick", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<div t-name="Child">Child</div>`; static template = xml`<div t-name="Child">Child</div>`;
} }
class App extends Component<any, any> { class App extends Component {
static template = xml` static template = xml`
<div> <div>
<button t-on-click="onClick">Click</button> <button t-on-click="onClick">Click</button>
@@ -458,7 +458,7 @@ describe("async rendering", () => {
const def = makeDeferred(); const def = makeDeferred();
let stateB; let stateB;
class ComponentC extends Component<any, any> { class ComponentC extends Component {
static template = xml`<span><t t-esc="props.fromA"/><t t-esc="someValue()"/></span>`; static template = xml`<span><t t-esc="props.fromA"/><t t-esc="someValue()"/></span>`;
someValue() { someValue() {
return this.props.fromB; return this.props.fromB;
@@ -469,7 +469,7 @@ describe("async rendering", () => {
} }
ComponentC.prototype.someValue = jest.fn(ComponentC.prototype.someValue); ComponentC.prototype.someValue = jest.fn(ComponentC.prototype.someValue);
class ComponentB extends Component<any, any> { class ComponentB extends Component {
static components = { ComponentC }; static components = { ComponentC };
static template = xml`<p><ComponentC fromA="props.fromA" fromB="state.fromB" /></p>`; static template = xml`<p><ComponentC fromA="props.fromA" fromB="state.fromB" /></p>`;
state = useState({ fromB: "b" }); state = useState({ fromB: "b" });
@@ -480,7 +480,7 @@ describe("async rendering", () => {
} }
} }
class ComponentA extends Component<any, any> { class ComponentA extends Component {
static components = { ComponentB }; static components = { ComponentB };
static template = xml`<div><ComponentB fromA="state.fromA"/></div>`; static template = xml`<div><ComponentB fromA="state.fromA"/></div>`;
state = useState({ fromA: 1 }); state = useState({ fromA: 1 });
@@ -514,14 +514,14 @@ describe("async rendering", () => {
const defs = [makeDeferred(), makeDeferred()]; const defs = [makeDeferred(), makeDeferred()];
let index = 0; let index = 0;
let stateB; let stateB;
class ComponentC extends Component<any, any> { class ComponentC extends Component {
static template = xml`<span><t t-esc="props.fromA"/><t t-esc="props.fromB"/></span>`; static template = xml`<span><t t-esc="props.fromA"/><t t-esc="props.fromB"/></span>`;
willUpdateProps() { willUpdateProps() {
return defs[index++]; return defs[index++];
} }
} }
class ComponentB extends Component<any, any> { class ComponentB extends Component {
static template = xml`<p><ComponentC fromA="props.fromA" fromB="state.fromB" /></p>`; static template = xml`<p><ComponentC fromA="props.fromA" fromB="state.fromB" /></p>`;
static components = { ComponentC }; static components = { ComponentC };
state = useState({ fromB: "b" }); state = useState({ fromB: "b" });
@@ -532,7 +532,7 @@ describe("async rendering", () => {
} }
} }
class ComponentA extends Component<any, any> { class ComponentA extends Component {
static template = xml`<div><t t-esc="state.fromA"/><ComponentB fromA="state.fromA"/></div>`; static template = xml`<div><t t-esc="state.fromA"/><ComponentB fromA="state.fromA"/></div>`;
static components = { ComponentB }; static components = { ComponentB };
state = useState({ fromA: 1 }); state = useState({ fromA: 1 });
@@ -564,14 +564,14 @@ describe("async rendering", () => {
const defs = [makeDeferred(), makeDeferred()]; const defs = [makeDeferred(), makeDeferred()];
let index = 0; let index = 0;
let stateB; let stateB;
class ComponentC extends Component<any, any> { class ComponentC extends Component {
static template = xml`<span><t t-esc="props.fromA"/><t t-esc="props.fromB"/></span>`; static template = xml`<span><t t-esc="props.fromA"/><t t-esc="props.fromB"/></span>`;
willUpdateProps() { willUpdateProps() {
return defs[index++]; return defs[index++];
} }
} }
class ComponentB extends Component<any, any> { class ComponentB extends Component {
static template = xml`<p><ComponentC fromA="props.fromA" fromB="state.fromB" /></p>`; static template = xml`<p><ComponentC fromA="props.fromA" fromB="state.fromB" /></p>`;
static components = { ComponentC }; static components = { ComponentC };
state = useState({ fromB: "b" }); state = useState({ fromB: "b" });
@@ -582,7 +582,7 @@ describe("async rendering", () => {
} }
} }
class ComponentA extends Component<any, any> { class ComponentA extends Component {
static template = xml`<div><ComponentB fromA="state.fromA"/></div>`; static template = xml`<div><ComponentB fromA="state.fromA"/></div>`;
static components = { ComponentB }; static components = { ComponentB };
state = useState({ fromA: 1 }); state = useState({ fromA: 1 });
@@ -616,7 +616,7 @@ describe("async rendering", () => {
let index = 0; let index = 0;
let stateC; let stateC;
class ComponentD extends Component<any, any> { class ComponentD extends Component {
static template = xml`<i><t t-esc="props.fromA"/><t t-esc="someValue()"/></i>`; static template = xml`<i><t t-esc="props.fromA"/><t t-esc="someValue()"/></i>`;
someValue() { someValue() {
return this.props.fromC; return this.props.fromC;
@@ -627,7 +627,7 @@ describe("async rendering", () => {
} }
ComponentD.prototype.someValue = jest.fn(ComponentD.prototype.someValue); ComponentD.prototype.someValue = jest.fn(ComponentD.prototype.someValue);
class ComponentC extends Component<any, any> { class ComponentC extends Component {
static template = xml`<span><ComponentD fromA="props.fromA" fromC="state.fromC" /></span>`; static template = xml`<span><ComponentD fromA="props.fromA" fromC="state.fromC" /></span>`;
static components = { ComponentD }; static components = { ComponentD };
state = useState({ fromC: "c" }); state = useState({ fromC: "c" });
@@ -637,7 +637,7 @@ describe("async rendering", () => {
} }
} }
class ComponentB extends Component<any, any> { class ComponentB extends Component {
static template = xml`<p><ComponentC fromA="props.fromA" /></p>`; static template = xml`<p><ComponentC fromA="props.fromA" /></p>`;
static components = { ComponentC }; static components = { ComponentC };
@@ -646,7 +646,7 @@ describe("async rendering", () => {
} }
} }
class ComponentA extends Component<any, any> { class ComponentA extends Component {
static components = { ComponentB }; static components = { ComponentB };
static template = xml`<div><ComponentB fromA="state.fromA"/></div>`; static template = xml`<div><ComponentB fromA="state.fromA"/></div>`;
state = useState({ fromA: 1 }); state = useState({ fromA: 1 });
@@ -686,7 +686,7 @@ describe("async rendering", () => {
let index = 0; let index = 0;
let stateC; let stateC;
class ComponentD extends Component<any, any> { class ComponentD extends Component {
static template = xml`<i><t t-esc="props.fromA"/><t t-esc="someValue()"/></i>`; static template = xml`<i><t t-esc="props.fromA"/><t t-esc="someValue()"/></i>`;
someValue() { someValue() {
return this.props.fromC; return this.props.fromC;
@@ -697,7 +697,7 @@ describe("async rendering", () => {
} }
ComponentD.prototype.someValue = jest.fn(ComponentD.prototype.someValue); ComponentD.prototype.someValue = jest.fn(ComponentD.prototype.someValue);
class ComponentC extends Component<any, any> { class ComponentC extends Component {
static template = xml`<span><ComponentD fromA="props.fromA" fromC="state.fromC" /></span>`; static template = xml`<span><ComponentD fromA="props.fromA" fromC="state.fromC" /></span>`;
static components = { ComponentD }; static components = { ComponentD };
state = useState({ fromC: "c" }); state = useState({ fromC: "c" });
@@ -707,7 +707,7 @@ describe("async rendering", () => {
} }
} }
class ComponentB extends Component<any, any> { class ComponentB extends Component {
static template = xml`<p><ComponentC fromA="props.fromA" /></p>`; static template = xml`<p><ComponentC fromA="props.fromA" /></p>`;
static components = { ComponentC }; static components = { ComponentC };
@@ -716,7 +716,7 @@ describe("async rendering", () => {
} }
} }
class ComponentA extends Component<any, any> { class ComponentA extends Component {
static components = { ComponentB }; static components = { ComponentB };
static template = xml`<div><ComponentB fromA="state.fromA"/></div>`; static template = xml`<div><ComponentB fromA="state.fromA"/></div>`;
state = useState({ fromA: 1 }); state = useState({ fromA: 1 });
@@ -754,7 +754,7 @@ describe("async rendering", () => {
const defsB = [makeDeferred(), makeDeferred()]; const defsB = [makeDeferred(), makeDeferred()];
let index = 0; let index = 0;
class ComponentB extends Component<any, any> { class ComponentB extends Component {
static template = xml`<p><t t-esc="someValue()" /></p>`; static template = xml`<p><t t-esc="someValue()" /></p>`;
someValue() { someValue() {
return this.props.fromA; return this.props.fromA;
@@ -765,7 +765,7 @@ describe("async rendering", () => {
} }
ComponentB.prototype.someValue = jest.fn(ComponentB.prototype.someValue); ComponentB.prototype.someValue = jest.fn(ComponentB.prototype.someValue);
class ComponentA extends Component<any, any> { class ComponentA extends Component {
static components = { ComponentB }; static components = { ComponentB };
static template = xml`<div><ComponentB fromA="state.fromA"/></div>`; static template = xml`<div><ComponentB fromA="state.fromA"/></div>`;
state = useState({ fromA: 1 }); state = useState({ fromA: 1 });
@@ -799,7 +799,7 @@ describe("async rendering", () => {
const defsB = [makeDeferred(), makeDeferred()]; const defsB = [makeDeferred(), makeDeferred()];
let index = 0; let index = 0;
class ComponentB extends Component<any, any> { class ComponentB extends Component {
static template = xml`<p><t t-esc="someValue()" /></p>`; static template = xml`<p><t t-esc="someValue()" /></p>`;
someValue() { someValue() {
return this.props.fromA; return this.props.fromA;
@@ -810,7 +810,7 @@ describe("async rendering", () => {
} }
ComponentB.prototype.someValue = jest.fn(ComponentB.prototype.someValue); ComponentB.prototype.someValue = jest.fn(ComponentB.prototype.someValue);
class ComponentA extends Component<any, any> { class ComponentA extends Component {
static components = { ComponentB }; static components = { ComponentB };
static template = xml`<div><ComponentB fromA="state.fromA"/></div>`; static template = xml`<div><ComponentB fromA="state.fromA"/></div>`;
state = useState({ fromA: 1 }); state = useState({ fromA: 1 });
@@ -841,7 +841,7 @@ describe("async rendering", () => {
}); });
test("concurrent renderings scenario 7", async () => { test("concurrent renderings scenario 7", async () => {
class ComponentB extends Component<any, any> { class ComponentB extends Component {
static template = xml`<p><t t-esc="props.fromA" /><t t-esc="someValue()" /></p>`; static template = xml`<p><t t-esc="props.fromA" /><t t-esc="someValue()" /></p>`;
state = useState({ fromB: "b" }); state = useState({ fromB: "b" });
someValue() { someValue() {
@@ -853,7 +853,7 @@ describe("async rendering", () => {
} }
ComponentB.prototype.someValue = jest.fn(ComponentB.prototype.someValue); ComponentB.prototype.someValue = jest.fn(ComponentB.prototype.someValue);
class ComponentA extends Component<any, any> { class ComponentA extends Component {
static components = { ComponentB }; static components = { ComponentB };
static template = xml`<div><ComponentB fromA="state.fromA"/></div>`; static template = xml`<div><ComponentB fromA="state.fromA"/></div>`;
state = useState({ fromA: 1 }); state = useState({ fromA: 1 });
@@ -874,7 +874,7 @@ describe("async rendering", () => {
test("concurrent renderings scenario 8", async () => { test("concurrent renderings scenario 8", async () => {
const def = makeDeferred(); const def = makeDeferred();
let stateB; let stateB;
class ComponentB extends Component<any, any> { class ComponentB extends Component {
static template = xml`<p><t t-esc="props.fromA" /><t t-esc="state.fromB" /></p>`; static template = xml`<p><t t-esc="props.fromA" /><t t-esc="state.fromB" /></p>`;
state = useState({ fromB: "b" }); state = useState({ fromB: "b" });
constructor(parent, props) { constructor(parent, props) {
@@ -886,7 +886,7 @@ describe("async rendering", () => {
} }
} }
class ComponentA extends Component<any, any> { class ComponentA extends Component {
static components = { ComponentB }; static components = { ComponentB };
static template = xml`<div><ComponentB fromA="state.fromA"/></div>`; static template = xml`<div><ComponentB fromA="state.fromA"/></div>`;
state = useState({ fromA: 1 }); state = useState({ fromA: 1 });
@@ -925,10 +925,10 @@ describe("async rendering", () => {
// re-rendering // re-rendering
const def = makeDeferred(); const def = makeDeferred();
let stateC; let stateC;
class ComponentD extends Component<any, any> { class ComponentD extends Component {
static template = xml`<span><t t-esc="props.fromA"/><t t-esc="props.fromC"/></span>`; static template = xml`<span><t t-esc="props.fromA"/><t t-esc="props.fromC"/></span>`;
} }
class ComponentC extends Component<any, any> { class ComponentC extends Component {
static template = xml`<p><ComponentD fromA="props.fromA" fromC="state.fromC" /></p>`; static template = xml`<p><ComponentD fromA="props.fromA" fromC="state.fromC" /></p>`;
static components = { ComponentD }; static components = { ComponentD };
state = useState({ fromC: "b1" }); state = useState({ fromC: "b1" });
@@ -938,13 +938,13 @@ describe("async rendering", () => {
stateC = this.state; stateC = this.state;
} }
} }
class ComponentB extends Component<any, any> { class ComponentB extends Component {
static template = xml`<b><t t-esc="props.fromA"/></b>`; static template = xml`<b><t t-esc="props.fromA"/></b>`;
willUpdateProps() { willUpdateProps() {
return def; return def;
} }
} }
class ComponentA extends Component<any, any> { class ComponentA extends Component {
static template = xml` static template = xml`
<div> <div>
<t t-esc="state.fromA"/> <t t-esc="state.fromA"/>
@@ -991,14 +991,14 @@ describe("async rendering", () => {
const defB = makeDeferred(); const defB = makeDeferred();
const defC = makeDeferred(); const defC = makeDeferred();
let stateB; let stateB;
class ComponentC extends Component<any, any> { class ComponentC extends Component {
static template = xml`<span><t t-esc="props.value"/></span>`; static template = xml`<span><t t-esc="props.value"/></span>`;
willStart() { willStart() {
return defC; return defC;
} }
} }
ComponentC.prototype.__render = jest.fn(ComponentC.prototype.__render); ComponentC.prototype.__render = jest.fn(ComponentC.prototype.__render);
class ComponentB extends Component<any, any> { class ComponentB extends Component {
static template = xml`<p><ComponentC t-if="state.hasChild" value="props.value"/></p>`; static template = xml`<p><ComponentC t-if="state.hasChild" value="props.value"/></p>`;
state = useState({ hasChild: false }); state = useState({ hasChild: false });
static components = { ComponentC }; static components = { ComponentC };
@@ -1010,7 +1010,7 @@ describe("async rendering", () => {
return defB; return defB;
} }
} }
class ComponentA extends Component<any, any> { class ComponentA extends Component {
static template = xml`<div><ComponentB value="state.value"/></div>`; static template = xml`<div><ComponentB value="state.value"/></div>`;
static components = { ComponentB }; static components = { ComponentB };
state = useState({ value: 1 }); state = useState({ value: 1 });
@@ -1042,7 +1042,7 @@ describe("async rendering", () => {
// remapped to the promise of the ambient rendering) // remapped to the promise of the ambient rendering)
const def = makeDeferred(); const def = makeDeferred();
let child; let child;
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="props.val"/>|<t t-esc="val"/></span>`; static template = xml`<span><t t-esc="props.val"/>|<t t-esc="val"/></span>`;
val = 3; val = 3;
willUpdateProps() { willUpdateProps() {
@@ -1051,7 +1051,7 @@ describe("async rendering", () => {
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child val="state.valA"/></div>`; static template = xml`<div><Child val="state.valA"/></div>`;
static components = { Child }; static components = { Child };
state = useState({ valA: 1 }); state = useState({ valA: 1 });
@@ -1079,14 +1079,14 @@ describe("async rendering", () => {
// rendered but not completed yet) // rendered but not completed yet)
const def = makeDeferred(); const def = makeDeferred();
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="props.val"/></span>`; static template = xml`<span><t t-esc="props.val"/></span>`;
willUpdateProps() { willUpdateProps() {
return def; return def;
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child val="state.val"/></div>`; static template = xml`<div><Child val="state.val"/></div>`;
static components = { Child }; static components = { Child };
state = useState({ val: 1 }); state = useState({ val: 1 });
@@ -1117,7 +1117,7 @@ describe("async rendering", () => {
test("concurrent renderings scenario 13", async () => { test("concurrent renderings scenario 13", async () => {
let lastChild; let lastChild;
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="state.val"/></span>`; static template = xml`<span><t t-esc="state.val"/></span>`;
state = useState({ val: 0 }); state = useState({ val: 0 });
mounted() { mounted() {
@@ -1129,7 +1129,7 @@ describe("async rendering", () => {
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml` static template = xml`
<div> <div>
<Child/> <Child/>
@@ -1153,7 +1153,7 @@ describe("async rendering", () => {
}); });
test("change state and call manually render: no unnecessary rendering", async () => { test("change state and call manually render: no unnecessary rendering", async () => {
class Widget extends Component<any, any> { class Widget extends Component {
static template = xml`<div><t t-esc="state.val"/></div>`; static template = xml`<div><t t-esc="state.val"/></div>`;
state = useState({ val: 1 }); state = useState({ val: 1 });
} }
+19 -19
View File
@@ -28,10 +28,10 @@ afterEach(() => {
describe("class and style attributes with t-component", () => { describe("class and style attributes with t-component", () => {
test("class is properly added on widget root el", async () => { test("class is properly added on widget root el", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<div class="c"/>`; static template = xml`<div class="c"/>`;
} }
class ParentWidget extends Component<any, any> { class ParentWidget extends Component {
static template = xml`<div><Child class="a b"/></div>`; static template = xml`<div><Child class="a b"/></div>`;
static components = { Child }; static components = { Child };
} }
@@ -41,10 +41,10 @@ describe("class and style attributes with t-component", () => {
}); });
test("empty class attribute is not added on widget root el", async () => { test("empty class attribute is not added on widget root el", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span/>`; static template = xml`<span/>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child class=""/></div>`; static template = xml`<div><Child class=""/></div>`;
static components = { Child }; static components = { Child };
} }
@@ -54,10 +54,10 @@ describe("class and style attributes with t-component", () => {
}); });
test("t-att-class is properly added/removed on widget root el", async () => { test("t-att-class is properly added/removed on widget root el", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<div class="c"/>`; static template = xml`<div class="c"/>`;
} }
class ParentWidget extends Component<any, any> { class ParentWidget extends Component {
static template = xml`<div><Child t-att-class="{a:state.a, b:state.b}"/></div>`; static template = xml`<div><Child t-att-class="{a:state.a, b:state.b}"/></div>`;
static components = { Child }; static components = { Child };
state = useState({ a: true, b: false }); state = useState({ a: true, b: false });
@@ -80,8 +80,8 @@ describe("class and style attributes with t-component", () => {
<Child class="a b c d"/> <Child class="a b c d"/>
</div>` </div>`
); );
class Child extends Component<any, any> {} class Child extends Component {}
class ParentWidget extends Component<any, any> { class ParentWidget extends Component {
static components = { Child }; static components = { Child };
} }
env.qweb.addTemplate("Child", `<div/>`); env.qweb.addTemplate("Child", `<div/>`);
@@ -99,10 +99,10 @@ describe("class and style attributes with t-component", () => {
<span t-name="Child" class="c" t-att-class="{ d: state.d }"/> <span t-name="Child" class="c" t-att-class="{ d: state.d }"/>
</templates>`); </templates>`);
class Child extends Component<any, any> { class Child extends Component {
state = useState({ d: true }); state = useState({ d: true });
} }
class ParentWidget extends Component<any, any> { class ParentWidget extends Component {
static components = { Child }; static components = { Child };
state = useState({ b: true }); state = useState({ b: true });
child = useRef("child"); child = useRef("child");
@@ -141,10 +141,10 @@ describe("class and style attributes with t-component", () => {
<span t-name="Child" class="c" t-att-class="state.d ? 'd' : ''"/> <span t-name="Child" class="c" t-att-class="state.d ? 'd' : ''"/>
</templates>`); </templates>`);
class Child extends Component<any, any> { class Child extends Component {
state = useState({ d: true }); state = useState({ d: true });
} }
class ParentWidget extends Component<any, any> { class ParentWidget extends Component {
static components = { Child }; static components = { Child };
state = useState({ b: true }); state = useState({ b: true });
child = useRef("child"); child = useRef("child");
@@ -180,7 +180,7 @@ describe("class and style attributes with t-component", () => {
<div t-name="App" t-att-class="{ c: state.c }" /> <div t-name="App" t-att-class="{ c: state.c }" />
</templates>`); </templates>`);
class App extends Component<any, any> { class App extends Component {
state = useState({ c: true }); state = useState({ c: true });
mounted() { mounted() {
this.el!.classList.add("user"); this.el!.classList.add("user");
@@ -207,11 +207,11 @@ describe("class and style attributes with t-component", () => {
</div>` </div>`
); );
class SomeComponent extends Component<any, any> { class SomeComponent extends Component {
static template = xml`<div/>`; static template = xml`<div/>`;
} }
class ParentWidget extends Component<any, any> { class ParentWidget extends Component {
static components = { child: SomeComponent }; static components = { child: SomeComponent };
} }
const widget = new ParentWidget(); const widget = new ParentWidget();
@@ -228,11 +228,11 @@ describe("class and style attributes with t-component", () => {
</div>` </div>`
); );
class SomeComponent extends Component<any, any> { class SomeComponent extends Component {
static template = xml`<div/>`; static template = xml`<div/>`;
} }
class ParentWidget extends Component<any, any> { class ParentWidget extends Component {
static components = { child: SomeComponent }; static components = { child: SomeComponent };
state = useState({ style: "font-size: 20px" }); state = useState({ style: "font-size: 20px" });
} }
@@ -250,10 +250,10 @@ describe("class and style attributes with t-component", () => {
}); });
test("error in subcomponent with class", async () => { test("error in subcomponent with class", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<div t-esc="this.will.crash"/>`; static template = xml`<div t-esc="this.will.crash"/>`;
} }
class ParentWidget extends Component<any, any> { class ParentWidget extends Component {
static template = xml`<div><Child class="a"/></div>`; static template = xml`<div><Child class="a"/></div>`;
static components = { Child }; static components = { Child };
} }
File diff suppressed because it is too large Load Diff
+32 -32
View File
@@ -41,10 +41,10 @@ describe("component error handling (catchError)", () => {
console.error = jest.fn(); console.error = jest.fn();
const handler = jest.fn(); const handler = jest.fn();
env.qweb.on("error", null, handler); env.qweb.on("error", null, handler);
class ErrorComponent extends Component<any, any> { class ErrorComponent extends Component {
static template = xml`<div>hey<t t-esc="props.flag and state.this.will.crash"/></div>`; static template = xml`<div>hey<t t-esc="props.flag and state.this.will.crash"/></div>`;
} }
class ErrorBoundary extends Component<any, any> { class ErrorBoundary extends Component {
static template = xml` static template = xml`
<div> <div>
<t t-if="state.error">Error handled</t> <t t-if="state.error">Error handled</t>
@@ -56,7 +56,7 @@ describe("component error handling (catchError)", () => {
this.state.error = true; this.state.error = true;
} }
} }
class App extends Component<any, any> { class App extends Component {
static template = xml` static template = xml`
<div> <div>
<ErrorBoundary><ErrorComponent flag="state.flag"/></ErrorBoundary> <ErrorBoundary><ErrorComponent flag="state.flag"/></ErrorBoundary>
@@ -83,11 +83,11 @@ describe("component error handling (catchError)", () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(); console.error = jest.fn();
class ErrorComponent extends Component<any, any> { class ErrorComponent extends Component {
static template = xml`<div>hey<t t-esc="props.flag and state.this.will.crash"/></div>`; static template = xml`<div>hey<t t-esc="props.flag and state.this.will.crash"/></div>`;
} }
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><ErrorComponent flag="state.flag"/></div>`; static template = xml`<div><ErrorComponent flag="state.flag"/></div>`;
static components = { ErrorComponent }; static components = { ErrorComponent };
state = useState({ flag: false }); state = useState({ flag: false });
@@ -117,10 +117,10 @@ describe("component error handling (catchError)", () => {
env.qweb.on("error", null, handler); env.qweb.on("error", null, handler);
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(); console.error = jest.fn();
class ErrorComponent extends Component<any, any> { class ErrorComponent extends Component {
static template = xml`<div>hey<t t-esc="state.this.will.crash"/></div>`; static template = xml`<div>hey<t t-esc="state.this.will.crash"/></div>`;
} }
class ErrorBoundary extends Component<any, any> { class ErrorBoundary extends Component {
static template = xml` static template = xml`
<div> <div>
<t t-if="state.error">Error handled</t> <t t-if="state.error">Error handled</t>
@@ -132,7 +132,7 @@ describe("component error handling (catchError)", () => {
this.state.error = true; this.state.error = true;
} }
} }
class App extends Component<any, any> { class App extends Component {
static template = xml` static template = xml`
<div> <div>
<ErrorBoundary><ErrorComponent /></ErrorBoundary> <ErrorBoundary><ErrorComponent /></ErrorBoundary>
@@ -153,10 +153,10 @@ describe("component error handling (catchError)", () => {
env.qweb.on("error", null, handler); env.qweb.on("error", null, handler);
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(); console.error = jest.fn();
class ErrorComponent extends Component<any, any> { class ErrorComponent extends Component {
static template = xml`<div>hey<t t-esc="state.this.will.crash"/></div>`; static template = xml`<div>hey<t t-esc="state.this.will.crash"/></div>`;
} }
class ErrorBoundary extends Component<any, any> { class ErrorBoundary extends Component {
static template = xml` static template = xml`
<div> <div>
<t t-if="state.error">Error handled</t> <t t-if="state.error">Error handled</t>
@@ -168,7 +168,7 @@ describe("component error handling (catchError)", () => {
this.state.error = true; this.state.error = true;
} }
} }
class App extends Component<any, any> { class App extends Component {
static template = xml` static template = xml`
<div> <div>
<ErrorBoundary t-if="state.flag"><ErrorComponent /></ErrorBoundary> <ErrorBoundary t-if="state.flag"><ErrorComponent /></ErrorBoundary>
@@ -203,20 +203,20 @@ describe("component error handling (catchError)", () => {
<ErrorBoundary><ErrorComponent /></ErrorBoundary> <ErrorBoundary><ErrorComponent /></ErrorBoundary>
</div> </div>
</templates>`); </templates>`);
class ErrorComponent extends Component<any, any> { class ErrorComponent extends Component {
constructor(parent) { constructor(parent) {
super(parent); super(parent);
throw new Error("NOOOOO"); throw new Error("NOOOOO");
} }
} }
class ErrorBoundary extends Component<any, any> { class ErrorBoundary extends Component {
state = useState({ error: false }); state = useState({ error: false });
catchError() { catchError() {
this.state.error = true; this.state.error = true;
} }
} }
class App extends Component<any, any> { class App extends Component {
static components = { ErrorBoundary, ErrorComponent }; static components = { ErrorBoundary, ErrorComponent };
} }
const app = new App(); const app = new App();
@@ -231,7 +231,7 @@ describe("component error handling (catchError)", () => {
test("can catch an error in the willStart call", async () => { test("can catch an error in the willStart call", async () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(); console.error = jest.fn();
class ErrorComponent extends Component<any, any> { class ErrorComponent extends Component {
static template = xml`<div t-name="ErrorComponent">Some text</div>`; static template = xml`<div t-name="ErrorComponent">Some text</div>`;
async willStart() { async willStart() {
// we wait a little bit to be in a different stack frame // we wait a little bit to be in a different stack frame
@@ -239,7 +239,7 @@ describe("component error handling (catchError)", () => {
throw new Error("NOOOOO"); throw new Error("NOOOOO");
} }
} }
class ErrorBoundary extends Component<any, any> { class ErrorBoundary extends Component {
static template = xml` static template = xml`
<div> <div>
<t t-if="state.error">Error handled</t> <t t-if="state.error">Error handled</t>
@@ -251,7 +251,7 @@ describe("component error handling (catchError)", () => {
this.state.error = true; this.state.error = true;
} }
} }
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><ErrorBoundary><ErrorComponent /></ErrorBoundary></div>`; static template = xml`<div><ErrorBoundary><ErrorComponent /></ErrorBoundary></div>`;
static components = { ErrorBoundary, ErrorComponent }; static components = { ErrorBoundary, ErrorComponent };
} }
@@ -277,19 +277,19 @@ describe("component error handling (catchError)", () => {
<ErrorBoundary><ErrorComponent /></ErrorBoundary> <ErrorBoundary><ErrorComponent /></ErrorBoundary>
</div> </div>
</templates>`); </templates>`);
class ErrorComponent extends Component<any, any> { class ErrorComponent extends Component {
mounted() { mounted() {
throw new Error("NOOOOO"); throw new Error("NOOOOO");
} }
} }
class ErrorBoundary extends Component<any, any> { class ErrorBoundary extends Component {
state = useState({ error: false }); state = useState({ error: false });
catchError() { catchError() {
this.state.error = true; this.state.error = true;
} }
} }
class App extends Component<any, any> { class App extends Component {
static components = { ErrorBoundary, ErrorComponent }; static components = { ErrorBoundary, ErrorComponent };
} }
const app = new App(); const app = new App();
@@ -304,13 +304,13 @@ describe("component error handling (catchError)", () => {
// we do not catch error in willPatch anymore // we do not catch error in willPatch anymore
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(); console.error = jest.fn();
class ErrorComponent extends Component<any, any> { class ErrorComponent extends Component {
static template = xml`<div><t t-esc="props.message"/></div>`; static template = xml`<div><t t-esc="props.message"/></div>`;
willPatch() { willPatch() {
throw new Error("NOOOOO"); throw new Error("NOOOOO");
} }
} }
class ErrorBoundary extends Component<any, any> { class ErrorBoundary extends Component {
static template = xml` static template = xml`
<div> <div>
<t t-if="state.error">Error handled</t> <t t-if="state.error">Error handled</t>
@@ -322,7 +322,7 @@ describe("component error handling (catchError)", () => {
this.state.error = true; this.state.error = true;
} }
} }
class App extends Component<any, any> { class App extends Component {
static template = xml` static template = xml`
<div> <div>
<span><t t-esc="state.message"/></span> <span><t t-esc="state.message"/></span>
@@ -347,7 +347,7 @@ describe("component error handling (catchError)", () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(() => {}); console.error = jest.fn(() => {});
// we do not catch error in willPatch anymore // we do not catch error in willPatch anymore
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><t t-esc="this.will.crash"/></div>`; static template = xml`<div><t t-esc="this.will.crash"/></div>`;
} }
@@ -369,7 +369,7 @@ describe("component error handling (catchError)", () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(() => {}); console.error = jest.fn(() => {});
class App extends Component<any, any> { class App extends Component {
static template = xml`<div>abc</div>`; static template = xml`<div>abc</div>`;
mounted() { mounted() {
throw new Error("boom"); throw new Error("boom");
@@ -395,7 +395,7 @@ describe("component error handling (catchError)", () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(() => {}); console.error = jest.fn(() => {});
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><t t-esc="val"/></div>`; static template = xml`<div><t t-esc="val"/></div>`;
val = 3; val = 3;
willPatch() { willPatch() {
@@ -424,7 +424,7 @@ describe("component error handling (catchError)", () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(() => {}); console.error = jest.fn(() => {});
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><t t-esc="val"/></div>`; static template = xml`<div><t t-esc="val"/></div>`;
val = 3; val = 3;
patched() { patched() {
@@ -453,10 +453,10 @@ describe("component error handling (catchError)", () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(() => {}); console.error = jest.fn(() => {});
// we do not catch error in willPatch anymore // we do not catch error in willPatch anymore
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<div><t t-esc="this.will.crash"/></div>`; static template = xml`<div><t t-esc="this.will.crash"/></div>`;
} }
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><Child/></div>`; static template = xml`<div><Child/></div>`;
static components = { Child }; static components = { Child };
} }
@@ -479,7 +479,7 @@ describe("component error handling (catchError)", () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(() => {}); console.error = jest.fn(() => {});
// we do not catch error in willPatch anymore // we do not catch error in willPatch anymore
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><t t-if="flag" t-esc="this.will.crash"/></div>`; static template = xml`<div><t t-if="flag" t-esc="this.will.crash"/></div>`;
flag = false; flag = false;
} }
@@ -502,10 +502,10 @@ describe("component error handling (catchError)", () => {
}); });
test("a rendering error will reject the render promise (with sub components)", async () => { test("a rendering error will reject the render promise (with sub components)", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span></span>`; static template = xml`<span></span>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child/><t t-esc="x.y"/></div>`; static template = xml`<div><Child/><t t-esc="x.y"/></div>`;
static components = { Child }; static components = { Child };
} }
+25 -25
View File
@@ -25,7 +25,7 @@ afterEach(() => {
QWeb.dev = dev; QWeb.dev = dev;
}); });
class Widget extends Component<any, any> {} class Widget extends Component {}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Tests // Tests
@@ -96,7 +96,7 @@ describe("props validation", () => {
]; ];
let props; let props;
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><TestWidget p="p"/></div>`; static template = xml`<div><TestWidget p="p"/></div>`;
get p() { get p() {
return props.p; return props.p;
@@ -153,14 +153,14 @@ describe("props validation", () => {
]; ];
let props; let props;
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><TestWidget p="p"/></div>`; static template = xml`<div><TestWidget p="p"/></div>`;
get p() { get p() {
return props.p; return props.p;
} }
} }
for (let test of Tests) { for (let test of Tests) {
let TestWidget = class extends Component<any, any> { let TestWidget = class extends Component {
static props = { p: { type: test.type } }; static props = { p: { type: test.type } };
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
}; };
@@ -200,11 +200,11 @@ describe("props validation", () => {
}); });
test("can validate a prop with multiple types", async () => { test("can validate a prop with multiple types", async () => {
class TestWidget extends Component<any, any> { class TestWidget extends Component {
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
static props = { p: [String, Boolean] }; static props = { p: [String, Boolean] };
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><TestWidget p="p"/></div>`; static template = xml`<div><TestWidget p="p"/></div>`;
static components = { TestWidget }; static components = { TestWidget };
get p() { get p() {
@@ -244,11 +244,11 @@ describe("props validation", () => {
}); });
test("can validate an optional props", async () => { test("can validate an optional props", async () => {
class TestWidget extends Component<any, any> { class TestWidget extends Component {
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
static props = { p: { type: String, optional: true } }; static props = { p: { type: String, optional: true } };
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><TestWidget p="p"/></div>`; static template = xml`<div><TestWidget p="p"/></div>`;
static components = { TestWidget }; static components = { TestWidget };
get p() { get p() {
@@ -288,11 +288,11 @@ describe("props validation", () => {
}); });
test("can validate an array with given primitive type", async () => { test("can validate an array with given primitive type", async () => {
class TestWidget extends Component<any, any> { class TestWidget extends Component {
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
static props = { p: { type: Array, element: String } }; static props = { p: { type: Array, element: String } };
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><TestWidget p="p"/></div>`; static template = xml`<div><TestWidget p="p"/></div>`;
static components = { TestWidget }; static components = { TestWidget };
get p() { get p() {
@@ -340,11 +340,11 @@ describe("props validation", () => {
}); });
test("can validate an array with multiple sub element types", async () => { test("can validate an array with multiple sub element types", async () => {
class TestWidget extends Component<any, any> { class TestWidget extends Component {
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
static props = { p: { type: Array, element: [String, Boolean] } }; static props = { p: { type: Array, element: [String, Boolean] } };
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><TestWidget p="p"/></div>`; static template = xml`<div><TestWidget p="p"/></div>`;
static components = { TestWidget }; static components = { TestWidget };
get p() { get p() {
@@ -393,13 +393,13 @@ describe("props validation", () => {
}); });
test("can validate an object with simple shape", async () => { test("can validate an object with simple shape", async () => {
class TestWidget extends Component<any, any> { class TestWidget extends Component {
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
static props = { static props = {
p: { type: Object, shape: { id: Number, url: String } } p: { type: Object, shape: { id: Number, url: String } }
}; };
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><TestWidget p="p"/></div>`; static template = xml`<div><TestWidget p="p"/></div>`;
static components = { TestWidget }; static components = { TestWidget };
get p() { get p() {
@@ -451,7 +451,7 @@ describe("props validation", () => {
}); });
test("can validate recursively complicated prop def", async () => { test("can validate recursively complicated prop def", async () => {
class TestWidget extends Component<any, any> { class TestWidget extends Component {
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
static props = { static props = {
p: { p: {
@@ -463,7 +463,7 @@ describe("props validation", () => {
} }
}; };
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><TestWidget p="p"/></div>`; static template = xml`<div><TestWidget p="p"/></div>`;
static components = { TestWidget }; static components = { TestWidget };
get p() { get p() {
@@ -503,7 +503,7 @@ describe("props validation", () => {
}); });
test("can validate optional attributes in nested sub props", () => { test("can validate optional attributes in nested sub props", () => {
class TestComponent extends Component<any, any> { class TestComponent extends Component {
static props = { static props = {
myprop: { myprop: {
type: Array, type: Array,
@@ -536,7 +536,7 @@ describe("props validation", () => {
}); });
test("can validate with a custom validator", () => { test("can validate with a custom validator", () => {
class TestComponent extends Component<any, any> { class TestComponent extends Component {
static props = { static props = {
size: { size: {
validate: e => ["small", "medium", "large"].includes(e) validate: e => ["small", "medium", "large"].includes(e)
@@ -562,7 +562,7 @@ describe("props validation", () => {
test("can validate with a custom validator, and a type", () => { test("can validate with a custom validator, and a type", () => {
const validator = jest.fn(n => 0 <= n && n <= 10); const validator = jest.fn(n => 0 <= n && n <= 10);
class TestComponent extends Component<any, any> { class TestComponent extends Component {
static props = { static props = {
n: { n: {
type: Number, type: Number,
@@ -738,7 +738,7 @@ describe("props validation", () => {
test("props are validated whenever component is updated", async () => { test("props are validated whenever component is updated", async () => {
let error; let error;
class TestWidget extends Component<any, any> { class TestWidget extends Component {
static props = { p: { type: Number } }; static props = { p: { type: Number } };
static template = xml`<div><t t-esc="props.p"/></div>`; static template = xml`<div><t t-esc="props.p"/></div>`;
@@ -750,7 +750,7 @@ describe("props validation", () => {
} }
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><TestWidget p="state.p"/></div>`; static template = xml`<div><TestWidget p="state.p"/></div>`;
static components = { TestWidget }; static components = { TestWidget };
state: any = useState({ p: 1 }); state: any = useState({ p: 1 });
@@ -767,12 +767,12 @@ describe("props validation", () => {
}); });
test("default values are applied before validating props at update", async () => { test("default values are applied before validating props at update", async () => {
class TestWidget extends Component<any, any> { class TestWidget extends Component {
static props = { p: { type: Number } }; static props = { p: { type: Number } };
static template = xml`<div><t t-esc="props.p"/></div>`; static template = xml`<div><t t-esc="props.p"/></div>`;
static defaultProps = { p: 4 }; static defaultProps = { p: 4 };
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><TestWidget p="state.p"/></div>`; static template = xml`<div><TestWidget p="state.p"/></div>`;
static components = { TestWidget }; static components = { TestWidget };
state: any = useState({ p: 1 }); state: any = useState({ p: 1 });
@@ -790,11 +790,11 @@ describe("props validation", () => {
describe("default props", () => { describe("default props", () => {
test("can set default values", async () => { test("can set default values", async () => {
class TestWidget extends Component<any, any> { class TestWidget extends Component {
static defaultProps = { p: 4 }; static defaultProps = { p: 4 };
static template = xml`<div><t t-esc="props.p"/></div>`; static template = xml`<div><t t-esc="props.p"/></div>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><TestWidget /></div>`; static template = xml`<div><TestWidget /></div>`;
static components = { TestWidget }; static components = { TestWidget };
} }
+70 -70
View File
@@ -26,7 +26,7 @@ afterEach(() => {
fixture.remove(); fixture.remove();
}); });
function children(w: Component<any, any>): Component<any, any>[] { function children(w: Component): Component[] {
const childrenMap = w.__owl__.children; const childrenMap = w.__owl__.children;
return Object.keys(childrenMap).map(id => childrenMap[id]); return Object.keys(childrenMap).map(id => childrenMap[id]);
} }
@@ -51,8 +51,8 @@ describe("t-slot directive", () => {
</div> </div>
</templates> </templates>
`); `);
class Dialog extends Component<any, any> {} class Dialog extends Component {}
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Dialog }; static components = { Dialog };
} }
const parent = new Parent(); const parent = new Parent();
@@ -68,13 +68,13 @@ describe("t-slot directive", () => {
}); });
test("named slots can define a default content", async () => { test("named slots can define a default content", async () => {
class Dialog extends Component<any, any> { class Dialog extends Component {
static template = xml` static template = xml`
<span> <span>
<t t-slot="header">default content</t> <t t-slot="header">default content</t>
</span>`; </span>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Dialog/></div>`; static template = xml`<div><Dialog/></div>`;
static components = { Dialog }; static components = { Dialog };
} }
@@ -86,13 +86,13 @@ describe("t-slot directive", () => {
}); });
test("dafault slots can define a default content", async () => { test("dafault slots can define a default content", async () => {
class Dialog extends Component<any, any> { class Dialog extends Component {
static template = xml` static template = xml`
<span> <span>
<t t-slot="default">default content</t> <t t-slot="default">default content</t>
</span>`; </span>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Dialog/></div>`; static template = xml`<div><Dialog/></div>`;
static components = { Dialog }; static components = { Dialog };
} }
@@ -104,13 +104,13 @@ describe("t-slot directive", () => {
}); });
test("default content is not rendered if slot is provided", async () => { test("default content is not rendered if slot is provided", async () => {
class Dialog extends Component<any, any> { class Dialog extends Component {
static template = xml` static template = xml`
<span> <span>
<t t-slot="default">default content</t> <t t-slot="default">default content</t>
</span>`; </span>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Dialog>hey</Dialog></div>`; static template = xml`<div><Dialog>hey</Dialog></div>`;
static components = { Dialog }; static components = { Dialog };
} }
@@ -121,13 +121,13 @@ describe("t-slot directive", () => {
}); });
test("default content is not rendered if named slot is provided", async () => { test("default content is not rendered if named slot is provided", async () => {
class Dialog extends Component<any, any> { class Dialog extends Component {
static template = xml` static template = xml`
<span> <span>
<t t-slot="header">default content</t> <t t-slot="header">default content</t>
</span>`; </span>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Dialog><t t-set="header">hey</t></Dialog></div>`; static template = xml`<div><Dialog><t t-set="header">hey</t></Dialog></div>`;
static components = { Dialog }; static components = { Dialog };
} }
@@ -149,8 +149,8 @@ describe("t-slot directive", () => {
<span t-name="Dialog"><t t-slot="footer"/></span> <span t-name="Dialog"><t t-slot="footer"/></span>
</templates> </templates>
`); `);
class Dialog extends Component<any, any> {} class Dialog extends Component {}
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Dialog }; static components = { Dialog };
state = useState({ val: 0 }); state = useState({ val: 0 });
doSomething() { doSomething() {
@@ -186,9 +186,9 @@ describe("t-slot directive", () => {
</div> </div>
</templates> </templates>
`); `);
class Link extends Component<any, any> {} class Link extends Component {}
class App extends Component<any, any> { class App extends Component {
state = useState({ state = useState({
users: [ users: [
{ id: 1, name: "Aaron" }, { id: 1, name: "Aaron" },
@@ -230,9 +230,9 @@ describe("t-slot directive", () => {
</div> </div>
</templates> </templates>
`); `);
class Link extends Component<any, any> {} class Link extends Component {}
class App extends Component<any, any> { class App extends Component {
state = useState({ state = useState({
users: [ users: [
{ id: 1, name: "Aaron" }, { id: 1, name: "Aaron" },
@@ -272,9 +272,9 @@ describe("t-slot directive", () => {
</div> </div>
</templates> </templates>
`); `);
class Link extends Component<any, any> {} class Link extends Component {}
class App extends Component<any, any> { class App extends Component {
state = useState({ user: { id: 1, name: "Aaron" } }); state = useState({ user: { id: 1, name: "Aaron" } });
static components = { Link }; static components = { Link };
} }
@@ -294,10 +294,10 @@ describe("t-slot directive", () => {
}); });
test("refs are properly bound in slots", async () => { test("refs are properly bound in slots", async () => {
class Dialog extends Component<any, any> { class Dialog extends Component {
static template = xml`<span><t t-slot="footer"/></span>`; static template = xml`<span><t t-slot="footer"/></span>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml` static template = xml`
<div> <div>
<span class="counter"><t t-esc="state.val"/></span> <span class="counter"><t t-esc="state.val"/></span>
@@ -340,8 +340,8 @@ describe("t-slot directive", () => {
<div t-name="Dialog"><t t-slot="default"/></div> <div t-name="Dialog"><t t-slot="default"/></div>
</templates> </templates>
`); `);
class Dialog extends Component<any, any> {} class Dialog extends Component {}
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Dialog }; static components = { Dialog };
} }
const parent = new Parent(); const parent = new Parent();
@@ -360,8 +360,8 @@ describe("t-slot directive", () => {
<div t-name="Dialog"><t t-slot="default"/></div> <div t-name="Dialog"><t t-slot="default"/></div>
</templates> </templates>
`); `);
class Dialog extends Component<any, any> {} class Dialog extends Component {}
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Dialog }; static components = { Dialog };
} }
const parent = new Parent(); const parent = new Parent();
@@ -385,8 +385,8 @@ describe("t-slot directive", () => {
<div t-name="Dialog"><t t-slot="content"/></div> <div t-name="Dialog"><t t-slot="content"/></div>
</templates> </templates>
`); `);
class Dialog extends Component<any, any> {} class Dialog extends Component {}
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Dialog }; static components = { Dialog };
} }
const parent = new Parent(); const parent = new Parent();
@@ -408,8 +408,8 @@ describe("t-slot directive", () => {
<div t-name="Dialog"><t t-slot="default"/></div> <div t-name="Dialog"><t t-slot="default"/></div>
</templates> </templates>
`); `);
class Dialog extends Component<any, any> {} class Dialog extends Component {}
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Dialog }; static components = { Dialog };
} }
const parent = new Parent(); const parent = new Parent();
@@ -432,8 +432,8 @@ describe("t-slot directive", () => {
</span> </span>
</templates> </templates>
`); `);
class Dialog extends Component<any, any> {} class Dialog extends Component {}
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Dialog }; static components = { Dialog };
} }
const parent = new Parent(); const parent = new Parent();
@@ -456,8 +456,8 @@ describe("t-slot directive", () => {
</span> </span>
</templates> </templates>
`); `);
class Dialog extends Component<any, any> {} class Dialog extends Component {}
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Dialog }; static components = { Dialog };
} }
const parent = new Parent(); const parent = new Parent();
@@ -478,9 +478,9 @@ describe("t-slot directive", () => {
<div t-name="GrandChild">Grand Child</div> <div t-name="GrandChild">Grand Child</div>
</templates> </templates>
`); `);
class Child extends Component<any, any> {} class Child extends Component {}
class GrandChild extends Component<any, any> {} class GrandChild extends Component {}
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Child, GrandChild }; static components = { Child, GrandChild };
} }
const parent = new Parent(); const parent = new Parent();
@@ -499,24 +499,24 @@ describe("t-slot directive", () => {
test("nested slots: evaluation context and parented relationship", async () => { test("nested slots: evaluation context and parented relationship", async () => {
let slot; let slot;
class Slot extends Component<any, any> { class Slot extends Component {
static template = xml`<span t-esc="props.val"/>`; static template = xml`<span t-esc="props.val"/>`;
constructor(parent, props) { constructor(parent, props) {
super(parent, props); super(parent, props);
slot = this; slot = this;
} }
} }
class GrandChild extends Component<any, any> { class GrandChild extends Component {
static template = xml`<div><t t-slot="default"/></div>`; static template = xml`<div><t t-slot="default"/></div>`;
} }
class Child extends Component<any, any> { class Child extends Component {
static components = { GrandChild }; static components = { GrandChild };
static template = xml` static template = xml`
<GrandChild> <GrandChild>
<t t-slot="default"/> <t t-slot="default"/>
</GrandChild>`; </GrandChild>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Child, Slot }; static components = { Child, Slot };
static template = xml`<Child><Slot val="state.val"/></Child>`; static template = xml`<Child><Slot val="state.val"/></Child>`;
state = useState({ val: 3 }); state = useState({ val: 3 });
@@ -548,9 +548,9 @@ describe("t-slot directive", () => {
</div> </div>
</templates> </templates>
`); `);
class SomeComponent extends Component<any, any> {} class SomeComponent extends Component {}
class GenericComponent extends Component<any, any> {} class GenericComponent extends Component {}
class App extends Component<any, any> { class App extends Component {
static components = { GenericComponent, SomeComponent }; static components = { GenericComponent, SomeComponent };
state = useState({ val: 4 }); state = useState({ val: 4 });
@@ -568,14 +568,14 @@ describe("t-slot directive", () => {
}); });
test("slots and wrapper components", async () => { test("slots and wrapper components", async () => {
class Link extends Component<any, any> { class Link extends Component {
static template = xml` static template = xml`
<a href="abc"> <a href="abc">
<t t-slot="default"/> <t t-slot="default"/>
</a>`; </a>`;
} }
class A extends Component<any, any> { class A extends Component {
static template = xml`<Link>hey</Link>`; static template = xml`<Link>hey</Link>`;
static components = { Link: Link }; static components = { Link: Link };
} }
@@ -587,14 +587,14 @@ describe("t-slot directive", () => {
}); });
test("template can just return a slot", async () => { test("template can just return a slot", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="props.value"/></span>`; static template = xml`<span><t t-esc="props.value"/></span>`;
} }
class SlotComponent extends Component<any, any> { class SlotComponent extends Component {
static template = xml`<t t-slot="default"/>`; static template = xml`<t t-slot="default"/>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml` static template = xml`
<div> <div>
<SlotComponent><Child value="state.value"/></SlotComponent> <SlotComponent><Child value="state.value"/></SlotComponent>
@@ -614,13 +614,13 @@ describe("t-slot directive", () => {
}); });
test("multiple slots containing components", async () => { test("multiple slots containing components", async () => {
class C extends Component<any, any> { class C extends Component {
static template = xml`<span><t t-esc="props.val"/></span>`; static template = xml`<span><t t-esc="props.val"/></span>`;
} }
class B extends Component<any, any> { class B extends Component {
static template = xml`<div><t t-slot="s1"/><t t-slot="s2"/></div>`; static template = xml`<div><t t-slot="s1"/><t t-slot="s2"/></div>`;
} }
class A extends Component<any, any> { class A extends Component {
static template = xml` static template = xml`
<B> <B>
<t t-set="s1"><C val="1"/></t> <t t-set="s1"><C val="1"/></t>
@@ -636,14 +636,14 @@ describe("t-slot directive", () => {
}); });
test("slots in t-foreach and re-rendering", async () => { test("slots in t-foreach and re-rendering", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="state.val"/><t t-slot="default"/></span>`; static template = xml`<span><t t-esc="state.val"/><t t-slot="default"/></span>`;
state = useState({ val: "A" }); state = useState({ val: "A" });
mounted() { mounted() {
this.state.val = "B"; this.state.val = "B";
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Child }; static components = { Child };
static template = xml` static template = xml`
<div> <div>
@@ -661,7 +661,7 @@ describe("t-slot directive", () => {
}); });
test("slots in t-foreach with t-set and re-rendering", async () => { test("slots in t-foreach with t-set and re-rendering", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml` static template = xml`
<span> <span>
<t t-esc="state.val"/> <t t-esc="state.val"/>
@@ -672,7 +672,7 @@ describe("t-slot directive", () => {
this.state.val = "B"; this.state.val = "B";
} }
} }
class ParentWidget extends Component<any, any> { class ParentWidget extends Component {
static components = { Child }; static components = { Child };
static template = xml` static template = xml`
<div> <div>
@@ -693,7 +693,7 @@ describe("t-slot directive", () => {
test("nested slots in same template", async () => { test("nested slots in same template", async () => {
let child, child2, child3; let child, child2, child3;
class Child extends Component<any, any> { class Child extends Component {
static template = xml` static template = xml`
<span id="c1"> <span id="c1">
<div> <div>
@@ -705,7 +705,7 @@ describe("t-slot directive", () => {
child = this; child = this;
} }
} }
class Child2 extends Component<any, any> { class Child2 extends Component {
static template = xml` static template = xml`
<span id="c2"> <span id="c2">
<t t-slot="default"/> <t t-slot="default"/>
@@ -715,7 +715,7 @@ describe("t-slot directive", () => {
child2 = this; child2 = this;
} }
} }
class Child3 extends Component<any, any> { class Child3 extends Component {
static template = xml` static template = xml`
<span>Child 3</span>`; <span>Child 3</span>`;
constructor(parent, props) { constructor(parent, props) {
@@ -723,7 +723,7 @@ describe("t-slot directive", () => {
child3 = this; child3 = this;
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Child, Child2, Child3 }; static components = { Child, Child2, Child3 };
static template = xml` static template = xml`
<span id="parent"> <span id="parent">
@@ -748,7 +748,7 @@ describe("t-slot directive", () => {
test("t-slot nested within another slot", async () => { test("t-slot nested within another slot", async () => {
let portal, modal, child3; let portal, modal, child3;
class Child3 extends Component<any, any> { class Child3 extends Component {
static template = xml` static template = xml`
<span>Child 3</span>`; <span>Child 3</span>`;
constructor(parent, props) { constructor(parent, props) {
@@ -756,7 +756,7 @@ describe("t-slot directive", () => {
child3 = this; child3 = this;
} }
} }
class Modal extends Component<any, any> { class Modal extends Component {
static template = xml` static template = xml`
<span id="modal"> <span id="modal">
<t t-slot="default"/> <t t-slot="default"/>
@@ -766,7 +766,7 @@ describe("t-slot directive", () => {
modal = this; modal = this;
} }
} }
class Portal extends Component<any, any> { class Portal extends Component {
static template = xml` static template = xml`
<span id="portal"> <span id="portal">
<t t-slot="default"/> <t t-slot="default"/>
@@ -776,7 +776,7 @@ describe("t-slot directive", () => {
portal = this; portal = this;
} }
} }
class Dialog extends Component<any, any> { class Dialog extends Component {
static components = { Modal, Portal }; static components = { Modal, Portal };
static template = xml` static template = xml`
<span id="c2"> <span id="c2">
@@ -787,7 +787,7 @@ describe("t-slot directive", () => {
</Modal> </Modal>
</span>`; </span>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Child3, Dialog }; static components = { Child3, Dialog };
static template = xml` static template = xml`
<span id="c1"> <span id="c1">
@@ -809,7 +809,7 @@ describe("t-slot directive", () => {
test("t-slot supports many instances", async () => { test("t-slot supports many instances", async () => {
let child3; let child3;
class Child3 extends Component<any, any> { class Child3 extends Component {
static template = xml` static template = xml`
<span>Child 3</span>`; <span>Child 3</span>`;
constructor(parent, props) { constructor(parent, props) {
@@ -817,13 +817,13 @@ describe("t-slot directive", () => {
child3 = this; child3 = this;
} }
} }
class Dialog extends Component<any, any> { class Dialog extends Component {
static template = xml` static template = xml`
<span id="c2"> <span id="c2">
<t t-slot="default"/> <t t-slot="default"/>
</span>`; </span>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Child3, Dialog }; static components = { Child3, Dialog };
static template = xml` static template = xml`
<span id="c1"> <span id="c1">
@@ -845,10 +845,10 @@ describe("t-slot directive", () => {
}); });
test("slots in slots, with vars", async () => { test("slots in slots, with vars", async () => {
class B extends Component<any, any> { class B extends Component {
static template = xml`<span><t t-slot="default"/></span>`; static template = xml`<span><t t-slot="default"/></span>`;
} }
class A extends Component<any, any> { class A extends Component {
static template = xml` static template = xml`
<div> <div>
<B> <B>
@@ -857,7 +857,7 @@ describe("t-slot directive", () => {
</div>`; </div>`;
static components = { B }; static components = { B };
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml` static template = xml`
<div> <div>
<t t-set="test" t-value="state.name"/> <t t-set="test" t-value="state.name"/>
+4 -4
View File
@@ -32,7 +32,7 @@ afterEach(() => {
describe("styles and component", () => { describe("styles and component", () => {
test("can define an inline stylesheet", async () => { test("can define an inline stylesheet", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml`<div class="app">text</div>`; static template = xml`<div class="app">text</div>`;
static style = css` static style = css`
.app { .app {
@@ -54,7 +54,7 @@ describe("styles and component", () => {
}); });
test("inherited components properly apply css", async () => { test("inherited components properly apply css", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml`<div class="app">text</div>`; static template = xml`<div class="app">text</div>`;
static style = css` static style = css`
.app { .app {
@@ -86,7 +86,7 @@ describe("styles and component", () => {
}); });
test("get a meaningful error message if css helper is missing", async () => { test("get a meaningful error message if css helper is missing", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml`<div class="app">text</div>`; static template = xml`<div class="app">text</div>`;
static style = `.app {color: red;}`; static style = `.app {color: red;}`;
} }
@@ -103,7 +103,7 @@ describe("styles and component", () => {
}); });
test("inline stylesheets are processed", async () => { test("inline stylesheets are processed", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml`<div class="app">text</div>`; static template = xml`<div class="app">text</div>`;
static style = css` static style = css`
.app { .app {
+19 -19
View File
@@ -27,7 +27,7 @@ afterEach(() => {
describe("mount targets", () => { describe("mount targets", () => {
test("can attach a component to an existing node (if same tagname)", async () => { test("can attach a component to an existing node (if same tagname)", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml`<div>app</div>`; static template = xml`<div>app</div>`;
} }
const div = document.createElement("div"); const div = document.createElement("div");
@@ -39,7 +39,7 @@ describe("mount targets", () => {
}); });
test("cannot attach a component to an existing node (if not same tagname)", async () => { test("cannot attach a component to an existing node (if not same tagname)", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml`<span>app</span>`; static template = xml`<span>app</span>`;
} }
const div = document.createElement("div"); const div = document.createElement("div");
@@ -57,7 +57,7 @@ describe("mount targets", () => {
}); });
test("can mount a component (with position='first-child')", async () => { test("can mount a component (with position='first-child')", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml`<div>app</div>`; static template = xml`<div>app</div>`;
} }
const span = document.createElement("span"); const span = document.createElement("span");
@@ -69,7 +69,7 @@ describe("mount targets", () => {
}); });
test("can mount a component (with position='last-child')", async () => { test("can mount a component (with position='last-child')", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml`<div>app</div>`; static template = xml`<div>app</div>`;
} }
const span = document.createElement("span"); const span = document.createElement("span");
@@ -81,7 +81,7 @@ describe("mount targets", () => {
}); });
test("default mount option is 'last-child'", async () => { test("default mount option is 'last-child'", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml`<div>app</div>`; static template = xml`<div>app</div>`;
} }
const span = document.createElement("span"); const span = document.createElement("span");
@@ -96,7 +96,7 @@ describe("mount targets", () => {
describe("unmounting and remounting", () => { describe("unmounting and remounting", () => {
test("widget can be unmounted and remounted", async () => { test("widget can be unmounted and remounted", async () => {
const steps: string[] = []; const steps: string[] = [];
class MyWidget extends Component<any, any> { class MyWidget extends Component {
static template = xml`<div>Hey</div>`; static template = xml`<div>Hey</div>`;
async willStart() { async willStart() {
steps.push("willstart"); steps.push("willstart");
@@ -128,7 +128,7 @@ describe("unmounting and remounting", () => {
test("widget can be mounted twice without ill effect", async () => { test("widget can be mounted twice without ill effect", async () => {
const steps: string[] = []; const steps: string[] = [];
class MyWidget extends Component<any, any> { class MyWidget extends Component {
static template = xml`<div>Hey</div>`; static template = xml`<div>Hey</div>`;
async willStart() { async willStart() {
steps.push("willstart"); steps.push("willstart");
@@ -151,7 +151,7 @@ describe("unmounting and remounting", () => {
test("state changes in willUnmount do not trigger rerender", async () => { test("state changes in willUnmount do not trigger rerender", async () => {
const steps: string[] = []; const steps: string[] = [];
class Child extends Component<any, any> { class Child extends Component {
static template = xml` static template = xml`
<span><t t-esc="props.val"/><t t-esc="state.n"/></span> <span><t t-esc="props.val"/><t t-esc="state.n"/></span>
`; `;
@@ -172,7 +172,7 @@ describe("unmounting and remounting", () => {
this.state.n = 3; this.state.n = 3;
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml` static template = xml`
<div> <div>
<Child t-if="state.flag" val="state.val"/> <Child t-if="state.flag" val="state.val"/>
@@ -193,7 +193,7 @@ describe("unmounting and remounting", () => {
}); });
test("state changes in willUnmount will be applied on remount", async () => { test("state changes in willUnmount will be applied on remount", async () => {
class TestWidget extends Component<any, any> { class TestWidget extends Component {
static template = xml` static template = xml`
<div><t t-esc="state.val"/></div> <div><t t-esc="state.val"/></div>
`; `;
@@ -216,7 +216,7 @@ describe("unmounting and remounting", () => {
}); });
test("sub component is still active after being unmounted and remounted", async () => { test("sub component is still active after being unmounted and remounted", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml` static template = xml`
<p t-on-click="state.value++"> <p t-on-click="state.value++">
<t t-esc="state.value"/> <t t-esc="state.value"/>
@@ -225,7 +225,7 @@ describe("unmounting and remounting", () => {
state = useState({ value: 1 }); state = useState({ value: 1 });
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Child }; static components = { Child };
static template = xml`<div><Child/></div>`; static template = xml`<div><Child/></div>`;
} }
@@ -248,7 +248,7 @@ describe("unmounting and remounting", () => {
test("change state just before mounting component", async () => { test("change state just before mounting component", async () => {
const steps: number[] = []; const steps: number[] = [];
class TestWidget extends Component<any, any> { class TestWidget extends Component {
static template = xml` static template = xml`
<div><t t-esc="state.val"/></div> <div><t t-esc="state.val"/></div>
`; `;
@@ -278,7 +278,7 @@ describe("unmounting and remounting", () => {
test("change state while mounting component", async () => { test("change state while mounting component", async () => {
const steps: number[] = []; const steps: number[] = [];
class TestWidget extends Component<any, any> { class TestWidget extends Component {
static template = xml` static template = xml`
<div><t t-esc="state.val"/></div> <div><t t-esc="state.val"/></div>
`; `;
@@ -312,7 +312,7 @@ describe("unmounting and remounting", () => {
test("change state while component is unmounted", async () => { test("change state while component is unmounted", async () => {
let child; let child;
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span t-esc="state.val"/>`; static template = xml`<span t-esc="state.val"/>`;
state = useState({ state = useState({
val: "C1" val: "C1"
@@ -323,7 +323,7 @@ describe("unmounting and remounting", () => {
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Child }; static components = { Child };
static template = xml`<div><t t-esc="state.val"/><Child/></div>`; static template = xml`<div><t t-esc="state.val"/><Child/></div>`;
state = useState({ val: "P1" }); state = useState({ val: "P1" });
@@ -345,7 +345,7 @@ describe("unmounting and remounting", () => {
test("unmount component during a re-rendering", async () => { test("unmount component during a re-rendering", async () => {
const def = makeDeferred(); const def = makeDeferred();
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="props.val"/></span>`; static template = xml`<span><t t-esc="props.val"/></span>`;
willUpdateProps() { willUpdateProps() {
return def; return def;
@@ -353,7 +353,7 @@ describe("unmounting and remounting", () => {
} }
Child.prototype.__render = jest.fn(Child.prototype.__render); Child.prototype.__render = jest.fn(Child.prototype.__render);
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child val="state.val"/></div>`; static template = xml`<div><Child val="state.val"/></div>`;
static components = { Child }; static components = { Child };
state = useState({ val: 1 }); state = useState({ val: 1 });
@@ -379,7 +379,7 @@ describe("unmounting and remounting", () => {
test("widget can be mounted on different target", async () => { test("widget can be mounted on different target", async () => {
const steps: string[] = []; const steps: string[] = [];
class MyWidget extends Component<any, any> { class MyWidget extends Component {
static template = xml`<div>Hey</div>`; static template = xml`<div>Hey</div>`;
async willStart() { async willStart() {
steps.push("willstart"); steps.push("willstart");
+21 -21
View File
@@ -32,7 +32,7 @@ describe("Context", () => {
test("very simple use, with initial value", async () => { test("very simple use, with initial value", async () => {
const testContext = new Context({ value: 123 }); const testContext = new Context({ value: 123 });
class Test extends Component<any, any> { class Test extends Component {
static template = xml`<div><t t-esc="contextObj.value"/></div>`; static template = xml`<div><t t-esc="contextObj.value"/></div>`;
contextObj = useContext(testContext); contextObj = useContext(testContext);
} }
@@ -44,7 +44,7 @@ describe("Context", () => {
test("useContext hook is reactive, for one component", async () => { test("useContext hook is reactive, for one component", async () => {
const testContext = new Context({ value: 123 }); const testContext = new Context({ value: 123 });
class Test extends Component<any, any> { class Test extends Component {
static template = xml`<div><t t-esc="contextObj.value"/></div>`; static template = xml`<div><t t-esc="contextObj.value"/></div>`;
contextObj = useContext(testContext); contextObj = useContext(testContext);
} }
@@ -59,11 +59,11 @@ describe("Context", () => {
test("two components can subscribe to same context", async () => { test("two components can subscribe to same context", async () => {
const testContext = new Context({ value: 123 }); const testContext = new Context({ value: 123 });
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="contextObj.value"/></span>`; static template = xml`<span><t t-esc="contextObj.value"/></span>`;
contextObj = useContext(testContext); contextObj = useContext(testContext);
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child /><Child /></div>`; static template = xml`<div><Child /><Child /></div>`;
static components = { Child }; static components = { Child };
} }
@@ -80,7 +80,7 @@ describe("Context", () => {
const def = makeDeferred(); const def = makeDeferred();
const steps: string[] = []; const steps: string[] = [];
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="contextObj.value"/></span>`; static template = xml`<span><t t-esc="contextObj.value"/></span>`;
contextObj = useContext(testContext); contextObj = useContext(testContext);
async render() { async render() {
@@ -90,7 +90,7 @@ describe("Context", () => {
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child /><Child /></div>`; static template = xml`<div><Child /><Child /></div>`;
static components = { Child }; static components = { Child };
} }
@@ -111,13 +111,13 @@ describe("Context", () => {
const def = makeDeferred(); const def = makeDeferred();
const steps: string[] = []; const steps: string[] = [];
class SlowComp extends Component<any, any> { class SlowComp extends Component {
static template = xml`<p><t t-esc="props.value"/></p>`; static template = xml`<p><t t-esc="props.value"/></p>`;
willUpdateProps() { willUpdateProps() {
return def; return def;
} }
} }
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><SlowComp value="contextObj.value"/></span>`; static template = xml`<span><SlowComp value="contextObj.value"/></span>`;
static components = { SlowComp }; static components = { SlowComp };
contextObj = useContext(testContext); contextObj = useContext(testContext);
@@ -128,12 +128,12 @@ describe("Context", () => {
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child /><Child /></div>`; static template = xml`<div><Child /><Child /></div>`;
static components = { Child }; static components = { Child };
} }
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><Child /><Parent /></div>`; static template = xml`<div><Child /><Parent /></div>`;
static components = { Child, Parent }; static components = { Child, Parent };
} }
@@ -166,7 +166,7 @@ describe("Context", () => {
const testContext = new Context({ a: 1, b: 2 }); const testContext = new Context({ a: 1, b: 2 });
const steps: string[] = []; const steps: string[] = [];
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="contextObj1.a"/><t t-esc="contextObj2.b"/></span>`; static template = xml`<span><t t-esc="contextObj1.a"/><t t-esc="contextObj2.b"/></span>`;
contextObj1 = useContext(testContext); contextObj1 = useContext(testContext);
contextObj2 = useContext(testContext); contextObj2 = useContext(testContext);
@@ -175,7 +175,7 @@ describe("Context", () => {
return super.__render(fiber); return super.__render(fiber);
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child /></div>`; static template = xml`<div><Child /></div>`;
static components = { Child }; static components = { Child };
} }
@@ -193,7 +193,7 @@ describe("Context", () => {
const testContext = new Context({ a: 123, b: 321 }); const testContext = new Context({ a: 123, b: 321 });
const steps: string[] = []; const steps: string[] = [];
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="contextObj.a"/></span>`; static template = xml`<span><t t-esc="contextObj.a"/></span>`;
contextObj = useContext(testContext); contextObj = useContext(testContext);
__render(fiber) { __render(fiber) {
@@ -201,7 +201,7 @@ describe("Context", () => {
return super.__render(fiber); return super.__render(fiber);
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child /><t t-esc="contextObj.b"/></div>`; static template = xml`<div><Child /><t t-esc="contextObj.b"/></div>`;
static components = { Child }; static components = { Child };
contextObj = useContext(testContext); contextObj = useContext(testContext);
@@ -227,7 +227,7 @@ describe("Context", () => {
const testContext = new Context({ a: 123 }); const testContext = new Context({ a: 123 });
const steps: string[] = []; const steps: string[] = [];
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="contextObj.a"/></span>`; static template = xml`<span><t t-esc="contextObj.a"/></span>`;
contextObj = useContext(testContext); contextObj = useContext(testContext);
__render(fiber) { __render(fiber) {
@@ -235,7 +235,7 @@ describe("Context", () => {
return super.__render(fiber); return super.__render(fiber);
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child t-if="state.flag"/></div>`; static template = xml`<div><Child t-if="state.flag"/></div>`;
static components = { Child }; static components = { Child };
state = useState({ flag: true }); state = useState({ flag: true });
@@ -263,14 +263,14 @@ describe("Context", () => {
test("destroyed component before being mounted is inactive", async () => { test("destroyed component before being mounted is inactive", async () => {
const testContext = new Context({ a: 123 }); const testContext = new Context({ a: 123 });
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="contextObj.a"/></span>`; static template = xml`<span><t t-esc="contextObj.a"/></span>`;
contextObj = useContext(testContext); contextObj = useContext(testContext);
willStart() { willStart() {
return makeDeferred(); return makeDeferred();
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child t-if="state.flag"/></div>`; static template = xml`<div><Child t-if="state.flag"/></div>`;
static components = { Child }; static components = { Child };
state = useState({ flag: true }); state = useState({ flag: true });
@@ -293,7 +293,7 @@ describe("Context", () => {
const testContext = new Context({ x: { n: 1 }, key: "x" }); const testContext = new Context({ x: { n: 1 }, key: "x" });
const def = makeDeferred(); const def = makeDeferred();
let stateC; let stateC;
class ComponentC extends Component<any, any> { class ComponentC extends Component {
static template = xml`<span><t t-esc="context[props.key].n"/><t t-esc="state.x"/></span>`; static template = xml`<span><t t-esc="context[props.key].n"/><t t-esc="state.x"/></span>`;
context = useContext(testContext); context = useContext(testContext);
state = useState({ x: "a" }); state = useState({ x: "a" });
@@ -303,7 +303,7 @@ describe("Context", () => {
stateC = this.state; stateC = this.state;
} }
} }
class ComponentB extends Component<any, any> { class ComponentB extends Component {
static components = { ComponentC }; static components = { ComponentC };
static template = xml`<p><ComponentC key="props.key"/></p>`; static template = xml`<p><ComponentC key="props.key"/></p>`;
@@ -311,7 +311,7 @@ describe("Context", () => {
return def; return def;
} }
} }
class ComponentA extends Component<any, any> { class ComponentA extends Component {
static components = { ComponentB }; static components = { ComponentB };
static template = xml`<div><ComponentB key="context.key"/></div>`; static template = xml`<div><ComponentB key="context.key"/></div>`;
context = useContext(testContext); context = useContext(testContext);
+28 -28
View File
@@ -42,7 +42,7 @@ afterEach(() => {
describe("hooks", () => { describe("hooks", () => {
test("can use a state hook", async () => { test("can use a state hook", async () => {
class Counter extends Component<any, any> { class Counter extends Component {
static template = xml`<div><t t-esc="counter.value"/></div>`; static template = xml`<div><t t-esc="counter.value"/></div>`;
counter = useState({ value: 42 }); counter = useState({ value: 42 });
} }
@@ -64,7 +64,7 @@ describe("hooks", () => {
steps.push("willunmount"); steps.push("willunmount");
}); });
} }
class MyComponent extends Component<any, any> { class MyComponent extends Component {
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
constructor() { constructor() {
super(); super();
@@ -92,7 +92,7 @@ describe("hooks", () => {
steps.push("willunmount"); steps.push("willunmount");
}); });
} }
class MyComponent extends Component<any, any> { class MyComponent extends Component {
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
constructor(parent, props) { constructor(parent, props) {
super(parent, props); super(parent, props);
@@ -100,7 +100,7 @@ describe("hooks", () => {
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><MyComponent t-if="state.flag"/></div>`; static template = xml`<div><MyComponent t-if="state.flag"/></div>`;
static components = { MyComponent }; static components = { MyComponent };
state = useState({ flag: true }); state = useState({ flag: true });
@@ -126,7 +126,7 @@ describe("hooks", () => {
steps.push("hook:willunmount"); steps.push("hook:willunmount");
}); });
} }
class MyComponent extends Component<any, any> { class MyComponent extends Component {
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
constructor() { constructor() {
super(); super();
@@ -157,7 +157,7 @@ describe("hooks", () => {
steps.push("hook:willunmount"); steps.push("hook:willunmount");
}); });
} }
class MyComponent extends Component<any, any> { class MyComponent extends Component {
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
constructor(parent, props) { constructor(parent, props) {
super(parent, props); super(parent, props);
@@ -171,7 +171,7 @@ describe("hooks", () => {
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><MyComponent t-if="state.flag"/></div>`; static template = xml`<div><MyComponent t-if="state.flag"/></div>`;
static components = { MyComponent }; static components = { MyComponent };
state = useState({ flag: true }); state = useState({ flag: true });
@@ -197,7 +197,7 @@ describe("hooks", () => {
steps.push("hook:willunmount" + i); steps.push("hook:willunmount" + i);
}); });
} }
class MyComponent extends Component<any, any> { class MyComponent extends Component {
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
constructor() { constructor() {
super(); super();
@@ -219,7 +219,7 @@ describe("hooks", () => {
}); });
test("useRef hook", async () => { test("useRef hook", async () => {
class Counter extends Component<any, any> { class Counter extends Component {
static template = xml`<div><button t-ref="button"><t t-esc="value"/></button></div>`; static template = xml`<div><button t-ref="button"><t t-esc="value"/></button></div>`;
button = useRef("button"); button = useRef("button");
value = 0; value = 0;
@@ -241,7 +241,7 @@ describe("hooks", () => {
test("useRef hook is null if ref is removed ", async () => { test("useRef hook is null if ref is removed ", async () => {
expect.assertions(4); expect.assertions(4);
class TestRef extends Component<any, any> { class TestRef extends Component {
static template = xml`<div><span t-if="state.flag" t-ref="span">owl</span></div>`; static template = xml`<div><span t-if="state.flag" t-ref="span">owl</span></div>`;
spanRef = useRef("span"); spanRef = useRef("span");
state = useState({ flag: true }); state = useState({ flag: true });
@@ -261,10 +261,10 @@ describe("hooks", () => {
}); });
test("t-refs on widget are components", async () => { test("t-refs on widget are components", async () => {
class WidgetB extends Component<any, any> { class WidgetB extends Component {
static template = xml`<div>b</div>`; static template = xml`<div>b</div>`;
} }
class WidgetC extends Component<any, any> { class WidgetC extends Component {
static template = xml`<div class="outer-div">Hello<WidgetB t-ref="mywidgetb" /></div>`; static template = xml`<div class="outer-div">Hello<WidgetB t-ref="mywidgetb" /></div>`;
static components = { WidgetB }; static components = { WidgetB };
ref = useRef("mywidgetb"); ref = useRef("mywidgetb");
@@ -280,11 +280,11 @@ describe("hooks", () => {
test("t-refs are bound at proper timing", async () => { test("t-refs are bound at proper timing", async () => {
expect.assertions(2); expect.assertions(2);
class Widget extends Component<any, any> { class Widget extends Component {
static template = xml`<div>widget</div>`; static template = xml`<div>widget</div>`;
} }
class ParentWidget extends Component<any, any> { class ParentWidget extends Component {
static template = xml` static template = xml`
<div> <div>
<t t-foreach="state.list" t-as="elem" t-ref="child" t-key="elem" t-component="Widget"/> <t t-foreach="state.list" t-as="elem" t-ref="child" t-key="elem" t-component="Widget"/>
@@ -309,10 +309,10 @@ describe("hooks", () => {
test("t-refs are bound at proper timing (2)", async () => { test("t-refs are bound at proper timing (2)", async () => {
expect.assertions(10); expect.assertions(10);
class Widget extends Component<any, any> { class Widget extends Component {
static template = xml`<div>widget</div>`; static template = xml`<div>widget</div>`;
} }
class ParentWidget extends Component<any, any> { class ParentWidget extends Component {
static template = xml` static template = xml`
<div> <div>
<t t-if="state.child1" t-ref="child1" t-component="Widget"/> <t t-if="state.child1" t-ref="child1" t-component="Widget"/>
@@ -369,7 +369,7 @@ describe("hooks", () => {
}); });
} }
class MyComponent extends Component<any, any> { class MyComponent extends Component {
static template = xml`<div><t t-if="state.flag">hey</t></div>`; static template = xml`<div><t t-if="state.flag">hey</t></div>`;
state = useState({ flag: true }); state = useState({ flag: true });
@@ -403,7 +403,7 @@ describe("hooks", () => {
steps.push("hook:willPatch"); steps.push("hook:willPatch");
}); });
} }
class MyComponent extends Component<any, any> { class MyComponent extends Component {
static template = xml`<div><t t-if="state.flag">hey</t></div>`; static template = xml`<div><t t-if="state.flag">hey</t></div>`;
state = useState({ flag: true }); state = useState({ flag: true });
@@ -437,7 +437,7 @@ describe("hooks", () => {
steps.push("hook:willPatch" + i); steps.push("hook:willPatch" + i);
}); });
} }
class MyComponent extends Component<any, any> { class MyComponent extends Component {
static template = xml`<div>hey<t t-esc="state.value"/></div>`; static template = xml`<div>hey<t t-esc="state.value"/></div>`;
state = useState({ value: 1 }); state = useState({ value: 1 });
constructor() { constructor() {
@@ -473,7 +473,7 @@ describe("hooks", () => {
} }
test("simple input", async () => { test("simple input", async () => {
class SomeComponent extends Component<any, any> { class SomeComponent extends Component {
static template = xml` static template = xml`
<div> <div>
<input t-ref="input1"/> <input t-ref="input1"/>
@@ -494,7 +494,7 @@ describe("hooks", () => {
}); });
test("input in a t-if", async () => { test("input in a t-if", async () => {
class SomeComponent extends Component<any, any> { class SomeComponent extends Component {
static template = xml` static template = xml`
<div> <div>
<input t-ref="input1"/> <input t-ref="input1"/>
@@ -521,7 +521,7 @@ describe("hooks", () => {
}); });
test("can use sub env", async () => { test("can use sub env", async () => {
class TestComponent extends Component<any, any> { class TestComponent extends Component {
static template = xml`<div><t t-esc="env.val"/></div>`; static template = xml`<div><t t-esc="env.val"/></div>`;
constructor() { constructor() {
super(); super();
@@ -536,7 +536,7 @@ describe("hooks", () => {
}); });
test("parent and child env", async () => { test("parent and child env", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<div><t t-esc="env.val"/></div>`; static template = xml`<div><t t-esc="env.val"/></div>`;
constructor(parent, props) { constructor(parent, props) {
super(parent, props); super(parent, props);
@@ -544,7 +544,7 @@ describe("hooks", () => {
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><t t-esc="env.val"/><Child/></div>`; static template = xml`<div><t t-esc="env.val"/><Child/></div>`;
static components = { Child }; static components = { Child };
constructor() { constructor() {
@@ -568,14 +568,14 @@ describe("hooks", () => {
steps.push("onWillUpdateProps"); steps.push("onWillUpdateProps");
}); });
} }
class MyComponent extends Component<any, any> { class MyComponent extends Component {
static template = xml`<span><t t-esc="props.value"/></span>`; static template = xml`<span><t t-esc="props.value"/></span>`;
constructor(parent, props) { constructor(parent, props) {
super(parent, props); super(parent, props);
useMyHook(); useMyHook();
} }
} }
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><MyComponent value="state.value"/></div>`; static template = xml`<div><MyComponent value="state.value"/></div>`;
static components = { MyComponent }; static components = { MyComponent };
state = useState({ value: 1 }); state = useState({ value: 1 });
@@ -597,7 +597,7 @@ describe("hooks", () => {
test("useExternalListener", async () => { test("useExternalListener", async () => {
let n = 0; let n = 0;
class MyComponent extends Component<any, any> { class MyComponent extends Component {
static template = xml`<span><t t-esc="props.value"/></span>`; static template = xml`<span><t t-esc="props.value"/></span>`;
constructor(parent, props) { constructor(parent, props) {
super(parent, props); super(parent, props);
@@ -607,7 +607,7 @@ describe("hooks", () => {
n++; n++;
} }
} }
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><MyComponent t-if="state.flag"/></div>`; static template = xml`<div><MyComponent t-if="state.flag"/></div>`;
static components = { MyComponent }; static components = { MyComponent };
state = useState({ flag: false }); state = useState({ flag: false });
+6 -6
View File
@@ -27,7 +27,7 @@ afterEach(() => {
describe("Asyncroot", () => { describe("Asyncroot", () => {
test("delayed component with AsyncRoot component", async () => { test("delayed component with AsyncRoot component", async () => {
let def; let def;
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="props.val"/></span>`; static template = xml`<span><t t-esc="props.val"/></span>`;
} }
class AsyncChild extends Child { class AsyncChild extends Child {
@@ -35,7 +35,7 @@ describe("Asyncroot", () => {
return def; return def;
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml` static template = xml`
<div> <div>
<button t-on-click="updateApp">Update App State</button> <button t-on-click="updateApp">Update App State</button>
@@ -74,7 +74,7 @@ describe("Asyncroot", () => {
test("fast component with AsyncRoot", async () => { test("fast component with AsyncRoot", async () => {
let def; let def;
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="props.val"/></span>`; static template = xml`<span><t t-esc="props.val"/></span>`;
} }
class AsyncChild extends Child { class AsyncChild extends Child {
@@ -83,7 +83,7 @@ describe("Asyncroot", () => {
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml` static template = xml`
<div> <div>
<button t-on-click="updateApp">Update App State</button> <button t-on-click="updateApp">Update App State</button>
@@ -122,7 +122,7 @@ describe("Asyncroot", () => {
test("asyncroot component: mixed re-renderings", async () => { test("asyncroot component: mixed re-renderings", async () => {
let def; let def;
class Child extends Component<any, any> { class Child extends Component {
static template = xml` static template = xml`
<span t-on-click="increment"> <span t-on-click="increment">
<t t-esc="state.val"/>/<t t-esc="props.val"/> <t t-esc="state.val"/>/<t t-esc="props.val"/>
@@ -138,7 +138,7 @@ describe("Asyncroot", () => {
return def; return def;
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml` static template = xml`
<div> <div>
<button t-on-click="updateApp">Update App State</button> <button t-on-click="updateApp">Update App State</button>
+45 -45
View File
@@ -36,7 +36,7 @@ describe("Portal: Props validation", () => {
test("target is mandatory", async () => { test("target is mandatory", async () => {
const dev = QWeb.dev; const dev = QWeb.dev;
QWeb.dev = true; QWeb.dev = true;
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -61,7 +61,7 @@ describe("Portal: Props validation", () => {
test("target is not list", async () => { test("target is not list", async () => {
const dev = QWeb.dev; const dev = QWeb.dev;
QWeb.dev = true; QWeb.dev = true;
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -88,7 +88,7 @@ describe("Portal: Basic use and DOM placement", () => {
test("basic use of portal", async () => { test("basic use of portal", async () => {
const dev = QWeb.dev; const dev = QWeb.dev;
QWeb.dev = true; QWeb.dev = true;
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -113,7 +113,7 @@ describe("Portal: Basic use and DOM placement", () => {
}); });
test("conditional use of Portal", async () => { test("conditional use of Portal", async () => {
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -148,10 +148,10 @@ describe("Portal: Basic use and DOM placement", () => {
}); });
test("conditional use of Portal (with sub Component)", async () => { test("conditional use of Portal (with sub Component)", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<div><t t-esc="props.val"/></div>`; static template = xml`<div><t t-esc="props.val"/></div>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal, Child }; static components = { Portal, Child };
static template = xml` static template = xml`
<div> <div>
@@ -190,7 +190,7 @@ describe("Portal: Basic use and DOM placement", () => {
}); });
test("with target in template (before portal)", async () => { test("with target in template (before portal)", async () => {
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -210,7 +210,7 @@ describe("Portal: Basic use and DOM placement", () => {
}); });
test("with target in template (after portal)", async () => { test("with target in template (after portal)", async () => {
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -233,7 +233,7 @@ describe("Portal: Basic use and DOM placement", () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(() => {}); console.error = jest.fn(() => {});
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -260,7 +260,7 @@ describe("Portal: Basic use and DOM placement", () => {
test("portal with child and props", async () => { test("portal with child and props", async () => {
const steps: string[] = []; const steps: string[] = [];
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="props.val"/></span>`; static template = xml`<span><t t-esc="props.val"/></span>`;
mounted() { mounted() {
steps.push("mounted"); steps.push("mounted");
@@ -271,7 +271,7 @@ describe("Portal: Basic use and DOM placement", () => {
expect(outside.innerHTML).toBe("<span>2</span>"); expect(outside.innerHTML).toBe("<span>2</span>");
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal, Child }; static components = { Portal, Child };
static template = xml` static template = xml`
<div> <div>
@@ -298,7 +298,7 @@ describe("Portal: Basic use and DOM placement", () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(() => {}); console.error = jest.fn(() => {});
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -326,7 +326,7 @@ describe("Portal: Basic use and DOM placement", () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(() => {}); console.error = jest.fn(() => {});
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -354,7 +354,7 @@ describe("Portal: Basic use and DOM placement", () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(() => {}); console.error = jest.fn(() => {});
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -379,7 +379,7 @@ describe("Portal: Basic use and DOM placement", () => {
}); });
test("portal with dynamic body", async () => { test("portal with dynamic body", async () => {
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -405,7 +405,7 @@ describe("Portal: Basic use and DOM placement", () => {
const consoleError = console.error; const consoleError = console.error;
console.error = jest.fn(() => {}); console.error = jest.fn(() => {});
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -439,7 +439,7 @@ describe("Portal: Basic use and DOM placement", () => {
test("lifecycle hooks of portal sub component are properly called", async () => { test("lifecycle hooks of portal sub component are properly called", async () => {
const steps: any[] = []; const steps: any[] = [];
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span t-esc="props.val"/>`; static template = xml`<span t-esc="props.val"/>`;
mounted() { mounted() {
steps.push("child:mounted"); steps.push("child:mounted");
@@ -454,7 +454,7 @@ describe("Portal: Basic use and DOM placement", () => {
steps.push("child:willUnmount"); steps.push("child:willUnmount");
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal, Child }; static components = { Portal, Child };
static template = xml` static template = xml`
<div> <div>
@@ -520,11 +520,11 @@ describe("Portal: Basic use and DOM placement", () => {
}); });
test("portal destroys on crash", async () => { test("portal destroys on crash", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span t-esc="props.error and this.will.crash" />`; static template = xml`<span t-esc="props.error and this.will.crash" />`;
state = {}; state = {};
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal, Child }; static components = { Portal, Child };
static template = xml` static template = xml`
<div> <div>
@@ -550,7 +550,7 @@ describe("Portal: Basic use and DOM placement", () => {
}); });
test("portal manual unmount", async () => { test("portal manual unmount", async () => {
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -577,7 +577,7 @@ describe("Portal: Basic use and DOM placement", () => {
test("portal manual unmount with subcomponent", async () => { test("portal manual unmount with subcomponent", async () => {
expect.assertions(9); expect.assertions(9);
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span>gloria</span>`; static template = xml`<span>gloria</span>`;
mounted() { mounted() {
expect(outside.contains(this.el)).toBeTruthy(); expect(outside.contains(this.el)).toBeTruthy();
@@ -586,7 +586,7 @@ describe("Portal: Basic use and DOM placement", () => {
expect(outside.contains(this.el)).toBeTruthy(); expect(outside.contains(this.el)).toBeTruthy();
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal, Child }; static components = { Portal, Child };
static template = xml` static template = xml`
<div> <div>
@@ -614,7 +614,7 @@ describe("Portal: Basic use and DOM placement", () => {
describe("Portal: Events handling", () => { describe("Portal: Events handling", () => {
test("events triggered on movable pure node are handled", async () => { test("events triggered on movable pure node are handled", async () => {
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal }; static components = { Portal };
static template = xml` static template = xml`
<div> <div>
@@ -638,8 +638,8 @@ describe("Portal: Events handling", () => {
}); });
test("events triggered on movable owl components are redirected", async () => { test("events triggered on movable owl components are redirected", async () => {
let childInst: Component<any, any> | null = null; let childInst: Component | null = null;
class Child extends Component<any, any> { class Child extends Component {
static template = xml` static template = xml`
<span t-on-custom="_onCustom" t-esc="props.val"/>`; <span t-on-custom="_onCustom" t-esc="props.val"/>`;
@@ -652,7 +652,7 @@ describe("Portal: Events handling", () => {
this.trigger("custom-portal"); this.trigger("custom-portal");
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal, Child }; static components = { Portal, Child };
static template = xml` static template = xml`
<div t-on-custom-portal="_onCustomPortal"> <div t-on-custom-portal="_onCustomPortal">
@@ -677,8 +677,8 @@ describe("Portal: Events handling", () => {
test("events triggered on contained movable owl components are redirected", async () => { test("events triggered on contained movable owl components are redirected", async () => {
const steps: string[] = []; const steps: string[] = [];
let childInst: Component<any, any> | null = null; let childInst: Component | null = null;
class Child extends Component<any, any> { class Child extends Component {
static template = xml` static template = xml`
<span t-on-custom="_onCustom"/>`; <span t-on-custom="_onCustom"/>`;
@@ -691,7 +691,7 @@ describe("Portal: Events handling", () => {
this.trigger("custom-portal"); this.trigger("custom-portal");
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal, Child }; static components = { Portal, Child };
static template = xml` static template = xml`
<div t-on-custom="_handled" t-on-custom-portal="_handled"> <div t-on-custom="_handled" t-on-custom-portal="_handled">
@@ -717,9 +717,9 @@ describe("Portal: Events handling", () => {
}); });
test("Dom events are not mapped", async () => { test("Dom events are not mapped", async () => {
let childInst: Component<any, any> | null = null; let childInst: Component | null = null;
const steps: string[] = []; const steps: string[] = [];
class Child extends Component<any, any> { class Child extends Component {
static template = xml` static template = xml`
<button>child</button>`; <button>child</button>`;
@@ -728,7 +728,7 @@ describe("Portal: Events handling", () => {
childInst = this; childInst = this;
} }
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal, Child }; static components = { Portal, Child };
static template = xml` static template = xml`
<div t-on-click="_handled"> <div t-on-click="_handled">
@@ -760,22 +760,22 @@ describe("Portal: Events handling", () => {
fixture.appendChild(outside2); fixture.appendChild(outside2);
const steps: Array<string> = []; const steps: Array<string> = [];
let childInst: Component<any, any> | null = null; let childInst: Component | null = null;
class Child2 extends Component<any, any> { class Child2 extends Component {
static template = xml`<div>child2</div>`; static template = xml`<div>child2</div>`;
constructor(parent, props) { constructor(parent, props) {
super(parent, props); super(parent, props);
childInst = this; childInst = this;
} }
} }
class Child extends Component<any, any> { class Child extends Component {
static components = { Portal, Child2 }; static components = { Portal, Child2 };
static template = xml` static template = xml`
<Portal target="'#outside2'"> <Portal target="'#outside2'">
<Child2 /> <Child2 />
</Portal>`; </Portal>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal, Child }; static components = { Portal, Child };
static template = xml` static template = xml`
<div t-on-custom='_handled'> <div t-on-custom='_handled'>
@@ -797,11 +797,11 @@ describe("Portal: Events handling", () => {
}); });
test("portal's parent's env is not polluted", async () => { test("portal's parent's env is not polluted", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml` static template = xml`
<button>child</button>`; <button>child</button>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal, Child }; static components = { Portal, Child };
static template = xml` static template = xml`
<div> <div>
@@ -818,22 +818,22 @@ describe("Portal: Events handling", () => {
test("Portal composed with t-slot", async () => { test("Portal composed with t-slot", async () => {
const steps: Array<string> = []; const steps: Array<string> = [];
let childInst: Component<any, any> | null = null; let childInst: Component | null = null;
class Child2 extends Component<any, any> { class Child2 extends Component {
static template = xml`<div>child2</div>`; static template = xml`<div>child2</div>`;
constructor(parent, props) { constructor(parent, props) {
super(parent, props); super(parent, props);
childInst = this; childInst = this;
} }
} }
class Child extends Component<any, any> { class Child extends Component {
static components = { Portal, Child2 }; static components = { Portal, Child2 };
static template = xml` static template = xml`
<Portal target="'#outside'"> <Portal target="'#outside'">
<t t-slot="default"/> <t t-slot="default"/>
</Portal>`; </Portal>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Child, Child2 }; static components = { Child, Child2 };
static template = xml` static template = xml`
<div t-on-custom='_handled'> <div t-on-custom='_handled'>
@@ -857,11 +857,11 @@ describe("Portal: Events handling", () => {
describe("Portal: UI/UX", () => { describe("Portal: UI/UX", () => {
test("focus is kept across re-renders", async () => { test("focus is kept across re-renders", async () => {
class Child extends Component<any, any> { class Child extends Component {
static template = xml` static template = xml`
<input id="target-me" t-att-placeholder="props.val"/>`; <input id="target-me" t-att-placeholder="props.val"/>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static components = { Portal, Child }; static components = { Portal, Child };
static template = xml` static template = xml`
<div> <div>
+2 -2
View File
@@ -31,7 +31,7 @@ describe("Link component", () => {
</div> </div>
</templates> </templates>
`); `);
class App extends Component<any, any> { class App extends Component {
static components = { Link: Link }; static components = { Link: Link };
} }
@@ -65,7 +65,7 @@ describe("Link component", () => {
</div> </div>
</templates> </templates>
`); `);
class App extends Component<any, any> { class App extends Component {
static components = { Link: Link }; static components = { Link: Link };
} }
+7 -7
View File
@@ -33,9 +33,9 @@ describe("RouteComponent", () => {
<span t-name="Users">Users</span> <span t-name="Users">Users</span>
</templates> </templates>
`); `);
class About extends Component<any, any> {} class About extends Component {}
class Users extends Component<any, any> {} class Users extends Component {}
class App extends Component<any, any> { class App extends Component {
static components = { RouteComponent }; static components = { RouteComponent };
} }
@@ -65,8 +65,8 @@ describe("RouteComponent", () => {
<span t-name="Book">Book <t t-esc="props.title"/></span> <span t-name="Book">Book <t t-esc="props.title"/></span>
</templates> </templates>
`); `);
class Book extends Component<any, any> {} class Book extends Component {}
class App extends Component<any, any> { class App extends Component {
static components = { RouteComponent }; static components = { RouteComponent };
} }
@@ -87,12 +87,12 @@ describe("RouteComponent", () => {
<span t-name="Book">Book <t t-esc="props.title"/>|<t t-esc="incVal"/></span> <span t-name="Book">Book <t t-esc="props.title"/>|<t t-esc="incVal"/></span>
</templates> </templates>
`); `);
class Book extends Component<any, any> { class Book extends Component {
get incVal() { get incVal() {
return this.props.val + 1; return this.props.val + 1;
} }
} }
class App extends Component<any, any> { class App extends Component {
static components = { RouteComponent }; static components = { RouteComponent };
} }
+44 -44
View File
@@ -29,7 +29,7 @@ describe("connecting a component to store", () => {
}; };
const store = new Store({ state, actions }); const store = new Store({ state, actions });
class App extends Component<any, any> { class App extends Component {
static template = xml` static template = xml`
<div> <div>
<span t-foreach="todos" t-key="todo.id" t-as="todo"><t t-esc="todo.msg"/></span> <span t-foreach="todos" t-key="todo.id" t-as="todo"><t t-esc="todo.msg"/></span>
@@ -60,7 +60,7 @@ describe("connecting a component to store", () => {
}; };
const store = new Store({ state, actions }); const store = new Store({ state, actions });
class App extends Component<any, any> { class App extends Component {
static template = xml` static template = xml`
<div> <div>
<span t-if="isBoolean">ok</span> <span t-if="isBoolean">ok</span>
@@ -102,7 +102,7 @@ describe("connecting a component to store", () => {
const state = { smallerArray: [1], biggerArray: [2, 3], useSmallArray: true }; const state = { smallerArray: [1], biggerArray: [2, 3], useSmallArray: true };
const store = new Store({ state }); const store = new Store({ state });
class App extends Component<any, any> { class App extends Component {
static template = xml`<div t-esc="mapAdd"/>`; static template = xml`<div t-esc="mapAdd"/>`;
storeProps = { storeProps = {
array: useStore(state => { array: useStore(state => {
@@ -131,7 +131,7 @@ describe("connecting a component to store", () => {
}); });
test("throw error if no store is found", async () => { test("throw error if no store is found", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml`<div></div>`; static template = xml`<div></div>`;
todos = useStore(state => state.todos); todos = useStore(state => state.todos);
} }
@@ -151,7 +151,7 @@ describe("connecting a component to store", () => {
const actions = {}; const actions = {};
const store = new Store({ state, actions }); const store = new Store({ state, actions });
class App extends Component<any, any> { class App extends Component {
static template = xml`<div/>`; static template = xml`<div/>`;
storeState = useStore(state => state.a); storeState = useStore(state => state.a);
} }
@@ -174,7 +174,7 @@ describe("connecting a component to store", () => {
}; };
const store = new Store({ state, actions }); const store = new Store({ state, actions });
class App extends Component<any, any> { class App extends Component {
static template = xml` static template = xml`
<div> <div>
<span t-esc="a.value"/> <span t-esc="a.value"/>
@@ -208,7 +208,7 @@ describe("connecting a component to store", () => {
}; };
const store = new Store({ state, actions }); const store = new Store({ state, actions });
class App extends Component<any, any> { class App extends Component {
static template = xml` static template = xml`
<div> <div>
<span t-foreach="todos" t-key="todo.id" t-as="todo"><t t-esc="todo.msg"/></span> <span t-foreach="todos" t-key="todo.id" t-as="todo"><t t-esc="todo.msg"/></span>
@@ -245,7 +245,7 @@ describe("connecting a component to store", () => {
}; };
const store = new Store({ state, actions }); const store = new Store({ state, actions });
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><t t-esc="nbrTodos.value"/></div>`; static template = xml`<div><t t-esc="nbrTodos.value"/></div>`;
nbrTodos = useStore(state => ({ value: state.todos.length })); nbrTodos = useStore(state => ({ value: state.todos.length }));
} }
@@ -273,7 +273,7 @@ describe("connecting a component to store", () => {
} }
}; };
const store = new Store({ state, actions }); const store = new Store({ state, actions });
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><t t-esc="nbrTodos.value"/></div>`; static template = xml`<div><t t-esc="nbrTodos.value"/></div>`;
nbrTodos = useStore(state => ({ value: state.todos.length }), { isEqual: shallowEqual }); nbrTodos = useStore(state => ({ value: state.todos.length }), { isEqual: shallowEqual });
} }
@@ -307,7 +307,7 @@ describe("connecting a component to store", () => {
}; };
const store = new Store({ state, actions }); const store = new Store({ state, actions });
class App extends Component<any, any> { class App extends Component {
static template = xml` static template = xml`
<div> <div>
<span t-foreach="todos" t-key="todo.id" t-as="todo"><t t-esc="todo.msg"/></span> <span t-foreach="todos" t-key="todo.id" t-as="todo"><t t-esc="todo.msg"/></span>
@@ -336,7 +336,7 @@ describe("connecting a component to store", () => {
}); });
(<any>env).store = store; (<any>env).store = store;
class App extends Component<any, any> { class App extends Component {
static template = xml` static template = xml`
<div> <div>
<button t-on-click="dispatch('inc')">Inc</button> <button t-on-click="dispatch('inc')">Inc</button>
@@ -365,14 +365,14 @@ describe("connecting a component to store", () => {
}; };
const store = new Store({ state, actions: {} }); const store = new Store({ state, actions: {} });
class TodoItem extends Component<any, any> { class TodoItem extends Component {
static template = xml`<span><t t-esc="todo.text"/></span>`; static template = xml`<span><t t-esc="todo.text"/></span>`;
todo = useStore((state, props) => { todo = useStore((state, props) => {
return state.todos.find(t => t.id === props.todoId); return state.todos.find(t => t.id === props.todoId);
}); });
} }
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><TodoItem todoId="state.currentId"/></div>`; static template = xml`<div><TodoItem todoId="state.currentId"/></div>`;
static components = { TodoItem }; static components = { TodoItem };
state = useState({ currentId: 1 }); state = useState({ currentId: 1 });
@@ -399,14 +399,14 @@ describe("connecting a component to store", () => {
}; };
const store = new Store({ state, actions }); const store = new Store({ state, actions });
class TodoItem extends Component<any, any> { class TodoItem extends Component {
static template = xml`<span><t t-esc="todo.text"/></span>`; static template = xml`<span><t t-esc="todo.text"/></span>`;
todo = useStore((state, props) => { todo = useStore((state, props) => {
return state.todos.find(t => t.id === props.id); return state.todos.find(t => t.id === props.id);
}); });
} }
class TodoList extends Component<any, any> { class TodoList extends Component {
static template = xml` static template = xml`
<div> <div>
<TodoItem t-foreach="todos" t-as="todo" id="todo.id" t-key="todo.id"/> <TodoItem t-foreach="todos" t-as="todo" id="todo.id" t-key="todo.id"/>
@@ -444,7 +444,7 @@ describe("connecting a component to store", () => {
}; };
const store = new Store({ state, getters }); const store = new Store({ state, getters });
class TodoItem extends Component<any, any> { class TodoItem extends Component {
static template = xml` static template = xml`
<div> <div>
<span><t t-esc="storeProps.activeTodoText"/></span> <span><t t-esc="storeProps.activeTodoText"/></span>
@@ -460,7 +460,7 @@ describe("connecting a component to store", () => {
}); });
} }
class TodoList extends Component<any, any> { class TodoList extends Component {
static components = { TodoItem }; static components = { TodoItem };
static template = xml` static template = xml`
<div> <div>
@@ -481,12 +481,12 @@ describe("connecting a component to store", () => {
}); });
test("connected component is updated when props are updated", async () => { test("connected component is updated when props are updated", async () => {
class Beer extends Component<any, any> { class Beer extends Component {
static template = xml`<span><t t-esc="beer.name"/></span>`; static template = xml`<span><t t-esc="beer.name"/></span>`;
beer = useStore((state, props) => state.beers[props.id]); beer = useStore((state, props) => state.beers[props.id]);
} }
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><Beer id="state.beerId"/></div>`; static template = xml`<div><Beer id="state.beerId"/></div>`;
static components = { Beer }; static components = { Beer };
state = useState({ beerId: 1 }); state = useState({ beerId: 1 });
@@ -506,7 +506,7 @@ describe("connecting a component to store", () => {
}); });
test("connected component is updated when store is changed", async () => { test("connected component is updated when store is changed", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml` static template = xml`
<div> <div>
<span t-foreach="data.beers" t-as="beer" t-key="beer.name"><t t-esc="beer.name"/></span> <span t-foreach="data.beers" t-as="beer" t-key="beer.name"><t t-esc="beer.name"/></span>
@@ -539,7 +539,7 @@ describe("connecting a component to store", () => {
test("connected component is updated when mixing store and props changes", async () => { test("connected component is updated when mixing store and props changes", async () => {
let counter = 0; let counter = 0;
class Beer extends Component<any, any> { class Beer extends Component {
static template = xml`<span><t t-esc="beer.name"/></span>`; static template = xml`<span><t t-esc="beer.name"/></span>`;
beer = useStore((state, props) => state.beers[props.id], { beer = useStore((state, props) => state.beers[props.id], {
onUpdate: result => { onUpdate: result => {
@@ -548,7 +548,7 @@ describe("connecting a component to store", () => {
}); });
} }
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><Beer id="state.beerId"/></div>`; static template = xml`<div><Beer id="state.beerId"/></div>`;
static components = { Beer }; static components = { Beer };
state = useState({ beerId: 1 }); state = useState({ beerId: 1 });
@@ -580,7 +580,7 @@ describe("connecting a component to store", () => {
}); });
test("connected component is properly cleaned up on destroy", async () => { test("connected component is properly cleaned up on destroy", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml`<div></div>`; static template = xml`<div></div>`;
state = useStore((state, props) => state); state = useStore((state, props) => state);
} }
@@ -599,7 +599,7 @@ describe("connecting a component to store", () => {
}); });
test("connected component with undefined, null and string props", async () => { test("connected component with undefined, null and string props", async () => {
class Beer extends Component<any, any> { class Beer extends Component {
static template = xml` static template = xml`
<div t-name="Beer"> <div t-name="Beer">
<span>taster:<t t-esc="data.taster"/></span> <span>taster:<t t-esc="data.taster"/></span>
@@ -613,7 +613,7 @@ describe("connecting a component to store", () => {
})); }));
} }
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><Beer id="state.beerId"/></div>`; static template = xml`<div><Beer id="state.beerId"/></div>`;
static components = { Beer }; static components = { Beer };
state = useState({ beerId: 0 }); state = useState({ beerId: 0 });
@@ -658,7 +658,7 @@ describe("connecting a component to store", () => {
}); });
test("connected component deeply reactive with undefined, null and string props", async () => { test("connected component deeply reactive with undefined, null and string props", async () => {
class Beer extends Component<any, any> { class Beer extends Component {
static template = xml` static template = xml`
<div> <div>
<span>taster:<t t-esc="info.taster"/></span> <span>taster:<t t-esc="info.taster"/></span>
@@ -674,7 +674,7 @@ describe("connecting a component to store", () => {
}); });
} }
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><Beer id="state.beerId"/></div>`; static template = xml`<div><Beer id="state.beerId"/></div>`;
static components = { Beer }; static components = { Beer };
state = useState({ beerId: 0 }); state = useState({ beerId: 0 });
@@ -749,7 +749,7 @@ describe("connecting a component to store", () => {
state.x.val = val; state.x.val = val;
} }
}; };
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><t t-esc="x.val"/></div>`; static template = xml`<div><t t-esc="x.val"/></div>`;
x = useStore(state => { x = useStore(state => {
return Object.assign({}, state.x); return Object.assign({}, state.x);
@@ -770,7 +770,7 @@ describe("connecting a component to store", () => {
test("correct update order when parent/children are connected", async () => { test("correct update order when parent/children are connected", async () => {
const steps: string[] = []; const steps: string[] = [];
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="state.msg"/></span>`; static template = xml`<span><t t-esc="state.msg"/></span>`;
state = useStore((state, props) => { state = useStore((state, props) => {
@@ -778,7 +778,7 @@ describe("connecting a component to store", () => {
return { msg: state.msg[props.key] }; return { msg: state.msg[props.key] };
}); });
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child key="state.current"/></div>`; static template = xml`<div><Child key="state.current"/></div>`;
static components = { Child }; static components = { Child };
@@ -817,7 +817,7 @@ describe("connecting a component to store", () => {
let def = makeDeferred(); let def = makeDeferred();
def.resolve(); def.resolve();
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="state.msg"/></span>`; static template = xml`<span><t t-esc="state.msg"/></span>`;
state = useStore((s, props) => { state = useStore((s, props) => {
steps.push("child"); steps.push("child");
@@ -825,7 +825,7 @@ describe("connecting a component to store", () => {
}); });
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml` static template = xml`
<div> <div>
<Child t-if="state.flag" someId="state.someId"/> <Child t-if="state.flag" someId="state.someId"/>
@@ -885,7 +885,7 @@ describe("connecting a component to store", () => {
actions actions
}); });
class TodoItem extends Component<any, any> { class TodoItem extends Component {
static template = xml` static template = xml`
<div class="todo"> <div class="todo">
<t t-esc="state.todo.title"/> <t t-esc="state.todo.title"/>
@@ -906,7 +906,7 @@ describe("connecting a component to store", () => {
return super.__render(f); return super.__render(f);
} }
} }
class TodoApp extends Component<any, any> { class TodoApp extends Component {
static template = xml` static template = xml`
<div class="todoapp"> <div class="todoapp">
<t t-foreach="Object.values(state.todos)" t-as="todo"> <t t-foreach="Object.values(state.todos)" t-as="todo">
@@ -958,7 +958,7 @@ describe("connecting a component to store", () => {
actions actions
}); });
class TodoItem extends Component<any, any> { class TodoItem extends Component {
static template = xml` static template = xml`
<div class="todo"> <div class="todo">
<t t-esc="state.todo.title"/> <t t-esc="state.todo.title"/>
@@ -980,7 +980,7 @@ describe("connecting a component to store", () => {
} }
} }
class TodoApp extends Component<any, any> { class TodoApp extends Component {
static template = xml` static template = xml`
<div class="todoapp"> <div class="todoapp">
<t t-foreach="Object.values(state.todos)" t-as="todo"> <t t-foreach="Object.values(state.todos)" t-as="todo">
@@ -1024,7 +1024,7 @@ describe("connecting a component to store", () => {
test("connected component willpatch/patch hooks are called on store updates", async () => { test("connected component willpatch/patch hooks are called on store updates", async () => {
const steps: string[] = []; const steps: string[] = [];
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><t t-esc="store.msg"/></div>`; static template = xml`<div><t t-esc="store.msg"/></div>`;
store = useStore(s => ({ msg: s.msg })); store = useStore(s => ({ msg: s.msg }));
@@ -1059,12 +1059,12 @@ describe("connecting a component to store", () => {
test("connected child components stop listening to store when destroyed", async () => { test("connected child components stop listening to store when destroyed", async () => {
let steps: any = []; let steps: any = [];
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<div><t t-esc="store.val"/></div>`; static template = xml`<div><t t-esc="store.val"/></div>`;
store = useStore(s => s); store = useStore(s => s);
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child t-if="state.child" /></div>`; static template = xml`<div><Child t-if="state.child" /></div>`;
static components = { Child }; static components = { Child };
state = useState({ child: true }); state = useState({ child: true });
@@ -1097,14 +1097,14 @@ describe("connecting a component to store", () => {
test("connected child component destroyed by dispatched action", async () => { test("connected child component destroyed by dispatched action", async () => {
let steps: any = []; let steps: any = [];
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<div><t t-esc="store.val"/></div>`; static template = xml`<div><t t-esc="store.val"/></div>`;
store = useStore(s => { store = useStore(s => {
steps.push("child selector"); steps.push("child selector");
return s; return s;
}); });
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child t-if="store.child" /></div>`; static template = xml`<div><Child t-if="store.child" /></div>`;
static components = { Child }; static components = { Child };
store = useStore(s => { store = useStore(s => {
@@ -1135,7 +1135,7 @@ describe("connecting a component to store", () => {
}); });
test("dispatch an action", async () => { test("dispatch an action", async () => {
class App extends Component<any, any> { class App extends Component {
static template = xml`<div><t t-esc="store.counter"/></div>`; static template = xml`<div><t t-esc="store.counter"/></div>`;
store = useStore(state => state); store = useStore(state => state);
dispatch = useDispatch(); dispatch = useDispatch();
@@ -1203,7 +1203,7 @@ describe("various scenarios", () => {
}; };
const store = new Store({ actions, state }); const store = new Store({ actions, state });
class Attachment extends Component<any, any> { class Attachment extends Component {
static template = xml` static template = xml`
<div> <div>
<span>Attachment <t t-esc="props.id"/></span> <span>Attachment <t t-esc="props.id"/></span>
@@ -1213,7 +1213,7 @@ describe("various scenarios", () => {
attachment = useStore((state, props) => ({ name: state.attachments[props.id].name })); attachment = useStore((state, props) => ({ name: state.attachments[props.id].name }));
} }
class Message extends Component<any, any> { class Message extends Component {
static template = xml` static template = xml`
<div> <div>
<button t-on-click="doStuff">Do stuff</button> <button t-on-click="doStuff">Do stuff</button>
+2 -2
View File
@@ -22,11 +22,11 @@ test("can log full lifecycle", async () => {
const log = console.log; const log = console.log;
console.log = arg => steps.push(arg); console.log = arg => steps.push(arg);
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<div>child</div>`; static template = xml`<div>child</div>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child t-if="state.flag"/></div>`; static template = xml`<div><Child t-if="state.flag"/></div>`;
static components = { Child }; static components = { Child };
state = useState({ flag: false }); state = useState({ flag: false });
+2 -2
View File
@@ -21,11 +21,11 @@ test("can log scheduler start and stop", async () => {
const log = console.log; const log = console.log;
console.log = arg => steps.push(arg); console.log = arg => steps.push(arg);
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<div>child</div>`; static template = xml`<div>child</div>`;
} }
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child /></div>`; static template = xml`<div><Child /></div>`;
static components = { Child }; static components = { Child };
} }
+1 -1
View File
@@ -21,7 +21,7 @@ test("log a specific message for render method calls if component is not mounted
const log = console.log; const log = console.log;
console.log = arg => steps.push(arg); console.log = arg => steps.push(arg);
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><t t-esc="state.value"/></div>`; static template = xml`<div><t t-esc="state.value"/></div>`;
state = owl.hooks.useState({ value: 1 }); state = owl.hooks.useState({ value: 1 });
} }
+2 -2
View File
@@ -21,14 +21,14 @@ test("log a sub component with non stringifiable props", async () => {
const log = console.log; const log = console.log;
console.log = arg => steps.push(arg); console.log = arg => steps.push(arg);
class Child extends Component<any, any> { class Child extends Component {
static template = xml`<span><t t-esc="props.obj.val"/></span>`; static template = xml`<span><t t-esc="props.obj.val"/></span>`;
} }
const circularObject: any = { val: 1 }; const circularObject: any = { val: 1 };
circularObject.circularObject = circularObject; circularObject.circularObject = circularObject;
class Parent extends Component<any, any> { class Parent extends Component {
static template = xml`<div><Child obj="obj"/></div>`; static template = xml`<div><Child obj="obj"/></div>`;
static components = { Child }; static components = { Child };
obj = circularObject; obj = circularObject;