mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ae81e9bee | |||
| 56cfc6403d | |||
| 276c8a0295 | |||
| 0717fe241d | |||
| 1291f1f175 | |||
| 6c0a3525c8 | |||
| 13241422e9 | |||
| 8f2c7f24d7 | |||
| fed9cc467f | |||
| 33174b301b |
Generated
+11
-11
@@ -2481,14 +2481,14 @@
|
||||
}
|
||||
},
|
||||
"git-rev-sync": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/git-rev-sync/-/git-rev-sync-1.12.0.tgz",
|
||||
"integrity": "sha512-LAeWoK54irAVyq/dHjkq13bYw8vsItGVCgZZbFFJv256DIK+VkLqXBjVvwtTgVWegOy7JVwD+w2uk63x+iLB6g==",
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/git-rev-sync/-/git-rev-sync-3.0.2.tgz",
|
||||
"integrity": "sha512-Nd5RiYpyncjLv0j6IONy0lGzAqdRXUaBctuGBbrEA2m6Bn4iDrN/9MeQTXuiquw8AEKL9D2BW0nw5m/lQvxqnQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"graceful-fs": "4.1.11",
|
||||
"shelljs": "0.7.7"
|
||||
"graceful-fs": "4.1.15",
|
||||
"shelljs": "0.8.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"escape-string-regexp": {
|
||||
@@ -2498,9 +2498,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||
"integrity": "sha512-9x6DLUuW+ROFdMTII9ec9t/FK8va6kYcC8/LggumssLM8kNv7IdFl3VrNUqgir2tJuBVxBga1QBoRziZacO5Zg==",
|
||||
"version": "4.1.15",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
|
||||
"integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@@ -5017,9 +5017,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"shelljs": {
|
||||
"version": "0.7.7",
|
||||
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.7.tgz",
|
||||
"integrity": "sha512-5ZXTlakejjdxXAnFl23pgPDzCcyPoshqMVWYqMH8HiP1R+i4auEKHabljL6XQlhQV58jkSRTR33Fq7OlxyLLTg==",
|
||||
"version": "0.8.5",
|
||||
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
|
||||
"integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.0.0",
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@odoo/owl",
|
||||
"version": "2.0.5",
|
||||
"version": "2.0.7",
|
||||
"description": "Odoo Web Library (OWL)",
|
||||
"main": "dist/owl.cjs.js",
|
||||
"module": "dist/owl.es.js",
|
||||
@@ -48,7 +48,7 @@
|
||||
"chalk": "^3.0.0",
|
||||
"current-git-branch": "^1.1.0",
|
||||
"eslint": "8.31.0",
|
||||
"git-rev-sync": "^1.12.0",
|
||||
"git-rev-sync": "^3.0.2",
|
||||
"github-api": "^3.3.0",
|
||||
"jest": "^27.1.0",
|
||||
"jest-diff": "^27.3.1",
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
ASTLog,
|
||||
ASTMulti,
|
||||
ASTSlot,
|
||||
ASTSlotDefinition,
|
||||
ASTTCall,
|
||||
ASTTCallBlock,
|
||||
ASTTEsc,
|
||||
@@ -137,12 +138,14 @@ interface Context {
|
||||
index: number | string;
|
||||
forceNewBlock: boolean;
|
||||
preventRoot?: boolean;
|
||||
ignoreRoot?: boolean;
|
||||
isLast?: boolean;
|
||||
translate: boolean;
|
||||
tKeyExpr: string | null;
|
||||
nameSpace?: string;
|
||||
tModelSelectedExpr?: string;
|
||||
ctxVar?: string;
|
||||
slotVar?: string;
|
||||
}
|
||||
|
||||
function createContext(parentCtx: Context, params?: Partial<Context>): Context {
|
||||
@@ -155,6 +158,7 @@ function createContext(parentCtx: Context, params?: Partial<Context>): Context {
|
||||
tKeyExpr: null,
|
||||
nameSpace: parentCtx.nameSpace,
|
||||
tModelSelectedExpr: parentCtx.tModelSelectedExpr,
|
||||
slotVar: parentCtx.slotVar
|
||||
},
|
||||
params
|
||||
);
|
||||
@@ -358,7 +362,7 @@ export class CodeGenerator {
|
||||
): BlockDescription {
|
||||
const hasRoot = this.target.hasRoot;
|
||||
const block = new BlockDescription(this.target, type);
|
||||
if (!hasRoot && !ctx.preventRoot) {
|
||||
if (!hasRoot && !ctx.preventRoot && !ctx.ignoreRoot) {
|
||||
this.target.hasRoot = true;
|
||||
block.isRoot = true;
|
||||
}
|
||||
@@ -384,6 +388,9 @@ export class CodeGenerator {
|
||||
blockExpr = `toggler(${ctx.tKeyExpr}, ${blockExpr})`;
|
||||
}
|
||||
|
||||
if (ctx.ignoreRoot) {
|
||||
return;
|
||||
}
|
||||
if (block.isRoot && !ctx.preventRoot) {
|
||||
if (this.target.on) {
|
||||
blockExpr = this.wrapWithEventCatcher(blockExpr, this.target.on);
|
||||
@@ -465,6 +472,8 @@ export class CodeGenerator {
|
||||
return this.compileLog(ast, ctx);
|
||||
case ASTType.TSlot:
|
||||
return this.compileTSlot(ast, ctx);
|
||||
case ASTType.TSetSlot:
|
||||
return this.compileTSetSlot(ast, ctx);
|
||||
case ASTType.TTranslation:
|
||||
return this.compileTTranslation(ast, ctx);
|
||||
case ASTType.TPortal:
|
||||
@@ -672,8 +681,9 @@ export class CodeGenerator {
|
||||
this.target.hasRef = true;
|
||||
const isDynamic = INTERP_REGEXP.test(ast.ref);
|
||||
if (isDynamic) {
|
||||
this.helpers.add("singleRefSetter");
|
||||
const str = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true));
|
||||
const idx = block!.insertData(`(el) => refs[${str}] = el`, "ref");
|
||||
const idx = block!.insertData(`singleRefSetter(refs, ${str})`, "ref");
|
||||
attrs["block-ref"] = String(idx);
|
||||
} else {
|
||||
let name = ast.ref;
|
||||
@@ -686,7 +696,8 @@ export class CodeGenerator {
|
||||
info[1] = `multiRefSetter(refs, \`${name}\`)`;
|
||||
} else {
|
||||
let id = generateId("ref");
|
||||
this.target.refInfo[name] = [id, `(el) => refs[\`${name}\`] = el`];
|
||||
this.helpers.add("singleRefSetter");
|
||||
this.target.refInfo[name] = [id, `singleRefSetter(refs, \`${name}\`)`];
|
||||
const index = block!.data.push(id) - 1;
|
||||
attrs["block-ref"] = String(index);
|
||||
}
|
||||
@@ -1142,52 +1153,38 @@ export class CodeGenerator {
|
||||
const props: string[] = ast.props ? this.formatPropObject(ast.props) : [];
|
||||
|
||||
// slots
|
||||
let slotDef: string = "";
|
||||
if (ast.slots) {
|
||||
let ctxStr = "ctx";
|
||||
if (this.target.loopLevel || !this.hasSafeContext) {
|
||||
ctxStr = generateId("ctx");
|
||||
this.helpers.add("capture");
|
||||
this.define(ctxStr, `capture(ctx)`);
|
||||
let slotVar: string = "";
|
||||
if (ast.body) {
|
||||
slotVar = generateId("slots");
|
||||
this.helpers.add("markRaw");
|
||||
if (ast.body.type === ASTType.TSetSlot) {
|
||||
const subCtx = createContext(ctx, { slotVar: undefined, ignoreRoot: true });
|
||||
const slotInfo = this.compileAST(ast.body, subCtx);
|
||||
this.target.addLine(`let ${slotVar} = markRaw({'${ast.body.name}': ${slotInfo}});`);
|
||||
|
||||
} else {
|
||||
this.target.addLine(`let ${slotVar} = markRaw({});`);
|
||||
const subCtx = createContext(ctx, { slotVar, ignoreRoot: true });
|
||||
this.compileAST(ast.body, subCtx);
|
||||
}
|
||||
let slotStr: string[] = [];
|
||||
for (let slotName in ast.slots) {
|
||||
const slotAst = ast.slots[slotName];
|
||||
const params = [];
|
||||
if (slotAst.content) {
|
||||
const name = this.compileInNewTarget("slot", slotAst.content, ctx, slotAst.on);
|
||||
params.push(`__render: ${name}.bind(this), __ctx: ${ctxStr}`);
|
||||
}
|
||||
const scope = ast.slots[slotName].scope;
|
||||
if (scope) {
|
||||
params.push(`__scope: "${scope}"`);
|
||||
}
|
||||
if (ast.slots[slotName].attrs) {
|
||||
params.push(...this.formatPropObject(ast.slots[slotName].attrs!));
|
||||
}
|
||||
const slotInfo = `{${params.join(", ")}}`;
|
||||
slotStr.push(`'${slotName}': ${slotInfo}`);
|
||||
}
|
||||
slotDef = `{${slotStr.join(", ")}}`;
|
||||
}
|
||||
|
||||
if (slotDef && !(ast.dynamicProps || hasSlotsProp)) {
|
||||
this.helpers.add("markRaw");
|
||||
props.push(`slots: markRaw(${slotDef})`);
|
||||
if (slotVar && !(ast.dynamicProps || hasSlotsProp)) {
|
||||
props.push(`slots: ${slotVar}`);
|
||||
}
|
||||
|
||||
let propString = this.getPropString(props, ast.dynamicProps);
|
||||
|
||||
let propVar: string;
|
||||
if ((slotDef && (ast.dynamicProps || hasSlotsProp)) || this.dev) {
|
||||
if ((slotVar && (ast.dynamicProps || hasSlotsProp)) || this.dev) {
|
||||
propVar = generateId("props");
|
||||
this.define(propVar!, propString);
|
||||
propString = propVar!;
|
||||
}
|
||||
|
||||
if (slotDef && (ast.dynamicProps || hasSlotsProp)) {
|
||||
if (slotVar && (ast.dynamicProps || hasSlotsProp)) {
|
||||
this.helpers.add("markRaw");
|
||||
this.addLine(`${propVar!}.slots = markRaw(Object.assign(${slotDef}, ${propVar!}.slots))`);
|
||||
this.addLine(`${propVar!}.slots = markRaw(Object.assign(${slotVar}, ${propVar!}.slots))`);
|
||||
}
|
||||
|
||||
// cmap key
|
||||
@@ -1218,11 +1215,18 @@ export class CodeGenerator {
|
||||
id,
|
||||
expr: `app.createComponent(${
|
||||
ast.isDynamic ? null : expr
|
||||
}, ${!ast.isDynamic}, ${!!ast.slots}, ${!!ast.dynamicProps}, ${
|
||||
}, ${!ast.isDynamic}, ${!!ast.body}, ${!!ast.dynamicProps}, ${
|
||||
!ast.props && !ast.dynamicProps
|
||||
})`,
|
||||
});
|
||||
|
||||
if (ast.isDynamic) {
|
||||
// If the component class changes, this can cause delayed renders to go
|
||||
// through if the key doesn't change. Use the component name for now.
|
||||
// This means that two component classes with the same name isn't supported
|
||||
// in t-component. We can generate a unique id per class later if needed.
|
||||
keyArg = `(${expr}).name + ${keyArg}`;
|
||||
}
|
||||
let blockExpr = `${id}(${propString}, ${keyArg}, node, this, ${ast.isDynamic ? expr : null})`;
|
||||
if (ast.isDynamic) {
|
||||
blockExpr = `toggler(${expr}, ${blockExpr})`;
|
||||
@@ -1254,6 +1258,39 @@ export class CodeGenerator {
|
||||
return `${name}(${expr}, [${handlers.join(",")}])`;
|
||||
}
|
||||
|
||||
compileTSetSlot(ast: ASTSlotDefinition, ctx: Context): string {
|
||||
let ctxStr = "ctx";
|
||||
if (this.target.loopLevel || !this.hasSafeContext) {
|
||||
ctxStr = generateId("ctx");
|
||||
this.helpers.add("capture");
|
||||
this.define(ctxStr, `capture(ctx)`);
|
||||
}
|
||||
// let slotStr: string[] = [];
|
||||
// for (let slotName in ast.slots) {
|
||||
// const slotAst = ast.slots[slotName];
|
||||
const params = [];
|
||||
if (ast.content) {
|
||||
const name = this.compileInNewTarget("slot", ast.content, ctx, ast.on);
|
||||
params.push(`__render: ${name}.bind(this), __ctx: ${ctxStr}`);
|
||||
}
|
||||
// ast.scope
|
||||
// const scope = ast.slots[slotName].scope;
|
||||
if (ast.scope) {
|
||||
params.push(`__scope: "${ast.scope}"`);
|
||||
}
|
||||
if (ast.attrs) {
|
||||
params.push(...this.formatPropObject(ast.attrs!));
|
||||
}
|
||||
const slotInfo = `{${params.join(", ")}}`;
|
||||
if (ctx.slotVar) {
|
||||
this.target.addLine(`${ctx.slotVar}['${ast.name}'] = ${slotInfo};`)
|
||||
}
|
||||
// slotStr.push(`'${slotName}': ${slotInfo}`);
|
||||
// }
|
||||
// slotDef = `{${slotStr.join(", ")}}`;
|
||||
return slotInfo;
|
||||
}
|
||||
|
||||
compileTSlot(ast: ASTSlot, ctx: Context): string {
|
||||
this.helpers.add("callSlot");
|
||||
let { block } = ctx;
|
||||
|
||||
+88
-67
@@ -23,6 +23,7 @@ export const enum ASTType {
|
||||
TDebug,
|
||||
TLog,
|
||||
TSlot,
|
||||
TSetSlot,
|
||||
TCallBlock,
|
||||
TTranslation,
|
||||
TPortal,
|
||||
@@ -120,7 +121,9 @@ export interface ASTTCall {
|
||||
context: string | null;
|
||||
}
|
||||
|
||||
interface SlotDefinition {
|
||||
export interface ASTSlotDefinition {
|
||||
type: ASTType.TSetSlot;
|
||||
name: string;
|
||||
content: AST | null;
|
||||
scope: string | null;
|
||||
on: EventHandlers | null;
|
||||
@@ -134,7 +137,8 @@ export interface ASTComponent {
|
||||
dynamicProps: string | null;
|
||||
on: EventHandlers | null;
|
||||
props: { [name: string]: string } | null;
|
||||
slots: { [name: string]: SlotDefinition } | null;
|
||||
body: AST | null;
|
||||
// slots: { [name: string]: ASTSlotDefinition } | null;
|
||||
}
|
||||
|
||||
export interface ASTSlot {
|
||||
@@ -186,6 +190,7 @@ export type AST =
|
||||
| ASTTKey
|
||||
| ASTComponent
|
||||
| ASTSlot
|
||||
| ASTSlotDefinition
|
||||
| ASTTCallBlock
|
||||
| ASTLog
|
||||
| ASTDebug
|
||||
@@ -238,6 +243,7 @@ function parseNode(node: Node, ctx: ParsingContext): AST | null {
|
||||
parseTKey(node, ctx) ||
|
||||
parseTTranslation(node, ctx) ||
|
||||
parseTSlot(node, ctx) ||
|
||||
parseTSetSlot(node, ctx) ||
|
||||
parseTOutNode(node, ctx) ||
|
||||
parseComponent(node, ctx) ||
|
||||
parseDOMNode(node, ctx) ||
|
||||
@@ -573,12 +579,12 @@ function parseTCall(node: Element, ctx: ParsingContext): AST | null {
|
||||
ast.content = [tcall];
|
||||
return ast;
|
||||
}
|
||||
if (ast && ast.type === ASTType.TComponent) {
|
||||
return {
|
||||
...ast,
|
||||
slots: { default: { content: tcall, scope: null, on: null, attrs: null } },
|
||||
};
|
||||
}
|
||||
// if (ast && ast.type === ASTType.TComponent) {
|
||||
// return {
|
||||
// ...ast,
|
||||
// slots: { default: { content: tcall, scope: null, on: null, attrs: null } },
|
||||
// };
|
||||
// }
|
||||
}
|
||||
const body = parseChildren(node, ctx);
|
||||
|
||||
@@ -706,8 +712,8 @@ function parseComponent(node: Element, ctx: ParsingContext): AST | null {
|
||||
const dynamicProps = node.getAttribute("t-props");
|
||||
node.removeAttribute("t-props");
|
||||
|
||||
const defaultSlotScope = node.getAttribute("t-slot-scope");
|
||||
node.removeAttribute("t-slot-scope");
|
||||
// const defaultSlotScope = node.getAttribute("t-slot-scope");
|
||||
// node.removeAttribute("t-slot-scope");
|
||||
let on: ASTComponent["on"] = null;
|
||||
|
||||
let props: ASTComponent["props"] = null;
|
||||
@@ -727,67 +733,17 @@ function parseComponent(node: Element, ctx: ParsingContext): AST | null {
|
||||
}
|
||||
}
|
||||
|
||||
let slots: ASTComponent["slots"] | null = null;
|
||||
let body: ASTComponent["body"] = null;
|
||||
|
||||
// let slots: ASTComponent["slots"] | null = null;
|
||||
if (node.hasChildNodes()) {
|
||||
const clone = <Element>node.cloneNode(true);
|
||||
|
||||
// named slots
|
||||
const slotNodes = Array.from(clone.querySelectorAll("[t-set-slot]"));
|
||||
for (let slotNode of slotNodes) {
|
||||
if (slotNode.tagName !== "t") {
|
||||
throw new OwlError(
|
||||
`Directive 't-set-slot' can only be used on <t> nodes (used on a <${slotNode.tagName}>)`
|
||||
);
|
||||
}
|
||||
const name = slotNode.getAttribute("t-set-slot")!;
|
||||
|
||||
// check if this is defined in a sub component (in which case it should
|
||||
// be ignored)
|
||||
let el = slotNode.parentElement!;
|
||||
let isInSubComponent = false;
|
||||
while (el !== clone) {
|
||||
if (el!.hasAttribute("t-component") || el!.tagName[0] === el!.tagName[0].toUpperCase()) {
|
||||
isInSubComponent = true;
|
||||
break;
|
||||
}
|
||||
el = el.parentElement!;
|
||||
}
|
||||
if (isInSubComponent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
slotNode.removeAttribute("t-set-slot");
|
||||
slotNode.remove();
|
||||
const slotAst = parseNode(slotNode, ctx);
|
||||
let on: SlotDefinition["on"] = null;
|
||||
let attrs: Attrs | null = null;
|
||||
let scope: string | null = null;
|
||||
for (let attributeName of slotNode.getAttributeNames()) {
|
||||
const value = slotNode.getAttribute(attributeName)!;
|
||||
if (attributeName === "t-slot-scope") {
|
||||
scope = value;
|
||||
continue;
|
||||
} else if (attributeName.startsWith("t-on-")) {
|
||||
on = on || {};
|
||||
on[attributeName.slice(5)] = value;
|
||||
} else {
|
||||
attrs = attrs || {};
|
||||
attrs[attributeName] = value;
|
||||
}
|
||||
}
|
||||
slots = slots || {};
|
||||
slots[name] = { content: slotAst, on, attrs, scope };
|
||||
body = parseChildNodes(node, ctx);
|
||||
if (!node.querySelector('[t-set-slot]')) {
|
||||
body = {type: ASTType.TSetSlot, name: "default", content: body, on: null, attrs: null, scope: null}
|
||||
}
|
||||
|
||||
// default slot
|
||||
const defaultContent = parseChildNodes(clone, ctx);
|
||||
slots = slots || {};
|
||||
// t-set-slot="default" has priority over content
|
||||
if (defaultContent && !slots.default) {
|
||||
slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
|
||||
}
|
||||
}
|
||||
return { type: ASTType.TComponent, name, isDynamic, dynamicProps, props, slots, on };
|
||||
return { type: ASTType.TComponent, name, isDynamic, dynamicProps, props, body, on };
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -821,6 +777,71 @@ function parseTSlot(node: Element, ctx: ParsingContext): AST | null {
|
||||
};
|
||||
}
|
||||
|
||||
function parseTSetSlot(node: Element, ctx: ParsingContext): AST | null {
|
||||
if (!node.hasAttribute("t-set-slot")) {
|
||||
return null;
|
||||
}
|
||||
// const t = el.ownerDocument.createElement("t");
|
||||
|
||||
// const clone = <Element>node.cloneNode(true);
|
||||
|
||||
// // named slots
|
||||
// const slotNodes = Array.from(clone.querySelectorAll("[t-set-slot]"));
|
||||
// for (let slotNode of slotNodes) {
|
||||
if (node.tagName !== "t") {
|
||||
throw new OwlError(
|
||||
`Directive 't-set-slot' can only be used on <t> nodes (used on a <${node.tagName}>)`
|
||||
);
|
||||
}
|
||||
const name = node.getAttribute("t-set-slot")!;
|
||||
|
||||
// // check if this is defined in a sub component (in which case it should
|
||||
// // be ignored)
|
||||
// let el = slotNode.parentElement!;
|
||||
// let isInSubComponent = false;
|
||||
// while (el !== clone) {
|
||||
// if (el!.hasAttribute("t-component") || el!.tagName[0] === el!.tagName[0].toUpperCase()) {
|
||||
// isInSubComponent = true;
|
||||
// break;
|
||||
// }
|
||||
// el = el.parentElement!;
|
||||
// }
|
||||
// if (isInSubComponent) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
node.removeAttribute("t-set-slot");
|
||||
node.remove();
|
||||
const slotAst = parseNode(node, ctx);
|
||||
let on: ASTSlotDefinition["on"] = null;
|
||||
let attrs: Attrs | null = null;
|
||||
let scope: string | null = null;
|
||||
for (let attributeName of node.getAttributeNames()) {
|
||||
const value = node.getAttribute(attributeName)!;
|
||||
if (attributeName === "t-slot-scope") {
|
||||
scope = value;
|
||||
continue;
|
||||
} else if (attributeName.startsWith("t-on-")) {
|
||||
on = on || {};
|
||||
on[attributeName.slice(5)] = value;
|
||||
} else {
|
||||
attrs = attrs || {};
|
||||
attrs[attributeName] = value;
|
||||
}
|
||||
}
|
||||
// slots = slots || {};
|
||||
return { type: ASTType.TSetSlot, name, content: slotAst, on, attrs, scope };
|
||||
// }
|
||||
|
||||
// // default slot
|
||||
// const defaultContent = parseChildNodes(clone, ctx);
|
||||
// slots = slots || {};
|
||||
// // t-set-slot="default" has priority over content
|
||||
// if (defaultContent && !slots.default) {
|
||||
// slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
|
||||
// }
|
||||
}
|
||||
|
||||
function parseTTranslation(node: Element, ctx: ParsingContext): AST | null {
|
||||
if (node.getAttribute("t-translation") !== "off") {
|
||||
return null;
|
||||
|
||||
+5
-1
@@ -1,7 +1,7 @@
|
||||
import { Component, ComponentConstructor, Props } from "./component";
|
||||
import { ComponentNode } from "./component_node";
|
||||
import { nodeErrorHandlers, OwlError, handleError } from "./error_handling";
|
||||
import { Fiber, MountOptions } from "./fibers";
|
||||
import { Fiber, RootFiber, MountOptions } from "./fibers";
|
||||
import { Scheduler } from "./scheduler";
|
||||
import { validateProps } from "./template_helpers";
|
||||
import { TemplateSet, TemplateSetConfig } from "./template_set";
|
||||
@@ -35,12 +35,16 @@ declare global {
|
||||
interface Window {
|
||||
__OWL_DEVTOOLS__: {
|
||||
apps: Set<App>;
|
||||
Fiber: typeof Fiber;
|
||||
RootFiber: typeof RootFiber;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
window.__OWL_DEVTOOLS__ ||= {
|
||||
apps: new Set<App>(),
|
||||
Fiber: Fiber,
|
||||
RootFiber: RootFiber,
|
||||
};
|
||||
|
||||
export class App<
|
||||
|
||||
@@ -162,10 +162,15 @@ export function getSubscriptions(callback: Callback) {
|
||||
const targets = callbacksToTargets.get(callback) || [];
|
||||
return [...targets].map((target) => {
|
||||
const keysToCallbacks = targetToKeysToCallbacks.get(target);
|
||||
return {
|
||||
target,
|
||||
keys: keysToCallbacks ? [...keysToCallbacks.keys()] : [],
|
||||
};
|
||||
let keys = [];
|
||||
if (keysToCallbacks) {
|
||||
for (const [key, cbs] of keysToCallbacks) {
|
||||
if (cbs.has(callback)) {
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return { target, keys };
|
||||
});
|
||||
}
|
||||
// Maps reactive objects to the underlying target
|
||||
|
||||
@@ -202,6 +202,16 @@ function multiRefSetter(refs: RefMap, name: string): RefSetter {
|
||||
};
|
||||
}
|
||||
|
||||
function singleRefSetter(refs: RefMap, name: string): RefSetter {
|
||||
let _el: HTMLElement | null = null;
|
||||
return (el) => {
|
||||
if (el || refs[name] === _el) {
|
||||
refs[name] = el;
|
||||
_el = el;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the component props (or next props) against the (static) props
|
||||
* description. This is potentially an expensive operation: it may needs to
|
||||
@@ -260,6 +270,7 @@ export const helpers = {
|
||||
prepareList,
|
||||
setContextValue,
|
||||
multiRefSetter,
|
||||
singleRefSetter,
|
||||
shallowEqual,
|
||||
toNumber,
|
||||
validateProps,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { OwlError } from "./error_handling";
|
||||
import { toRaw } from "./reactivity";
|
||||
|
||||
type BaseType =
|
||||
| typeof String
|
||||
@@ -84,6 +85,7 @@ export function validateSchema(obj: { [key: string]: any }, schema: Schema): str
|
||||
if (Array.isArray(schema)) {
|
||||
schema = toSchema(schema);
|
||||
}
|
||||
obj = toRaw(obj);
|
||||
let errors = [];
|
||||
// check if each value in obj has correct shape
|
||||
for (let key in obj) {
|
||||
|
||||
@@ -182,7 +182,7 @@ exports[`misc other complex template 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { prepareList, withKey } = helpers;
|
||||
let { prepareList, withKey, singleRefSetter } = helpers;
|
||||
const callTemplate_1 = app.getTemplate(\`LOAD_INFOS_TEMPLATE\`);
|
||||
const comp1 = app.createComponent(\`BundlesList\`, true, false, false, false);
|
||||
const comp2 = app.createComponent(\`BundlesList\`, true, false, false, false);
|
||||
@@ -218,8 +218,8 @@ exports[`misc other complex template 1`] = `
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`search_input\`] = el;
|
||||
const ref2 = (el) => refs[\`settings_menu\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`search_input\`);
|
||||
const ref2 = singleRefSetter(refs, \`settings_menu\`);
|
||||
let b2,b4,b14,b17,b22,b23,b24,b25;
|
||||
let attr1 = \`/runbot/\${ctx['project'].slug}\`;
|
||||
let txt1 = ctx['project'].name;
|
||||
|
||||
@@ -4,13 +4,14 @@ exports[`t-ref can get a dynamic ref on a node 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><span block-ref=\\"0\\"/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const v1 = ctx['id'];
|
||||
let ref1 = (el) => refs[\`myspan\${v1}\`] = el;
|
||||
let ref1 = singleRefSetter(refs, \`myspan\${v1}\`);
|
||||
return block1([ref1]);
|
||||
}
|
||||
}"
|
||||
@@ -20,13 +21,14 @@ exports[`t-ref can get a dynamic ref on a node, alternate syntax 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><span block-ref=\\"0\\"/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const v1 = ctx['id'];
|
||||
let ref1 = (el) => refs[\`myspan\${v1}\`] = el;
|
||||
let ref1 = singleRefSetter(refs, \`myspan\${v1}\`);
|
||||
return block1([ref1]);
|
||||
}
|
||||
}"
|
||||
@@ -36,12 +38,13 @@ exports[`t-ref can get a ref on a node 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><span block-ref=\\"0\\"/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`myspan\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`myspan\`);
|
||||
return block1([ref1]);
|
||||
}
|
||||
}"
|
||||
@@ -66,12 +69,13 @@ exports[`t-ref ref in a t-call 2`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div>1<span block-ref=\\"0\\"/>2</div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`name\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`name\`);
|
||||
return block1([ref1]);
|
||||
}
|
||||
}"
|
||||
@@ -81,13 +85,14 @@ exports[`t-ref ref in a t-if 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||
let block2 = createBlock(\`<span block-ref=\\"0\\"/>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`name\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`name\`);
|
||||
let b2;
|
||||
if (ctx['condition']) {
|
||||
b2 = block2([ref1]);
|
||||
@@ -101,7 +106,7 @@ exports[`t-ref refs in a loop 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { prepareList, withKey } = helpers;
|
||||
let { prepareList, singleRefSetter, withKey } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||
let block3 = createBlock(\`<div block-ref=\\"0\\"><block-text-1/></div>\`);
|
||||
@@ -115,7 +120,7 @@ exports[`t-ref refs in a loop 1`] = `
|
||||
const key1 = ctx['item'];
|
||||
const tKey_1 = ctx['item'];
|
||||
const v1 = ctx['item'];
|
||||
let ref1 = (el) => refs[(v1)] = el;
|
||||
let ref1 = singleRefSetter(refs, (v1));
|
||||
let txt1 = ctx['item'];
|
||||
c_block2[i1] = withKey(block3([ref1, txt1]), tKey_1 + key1);
|
||||
}
|
||||
@@ -129,14 +134,15 @@ exports[`t-ref two refs, one in a t-if 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-child-0/><p block-ref=\\"0\\"/></div>\`);
|
||||
let block2 = createBlock(\`<span block-ref=\\"0\\"/>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`name\`] = el;
|
||||
const ref2 = (el) => refs[\`p\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`name\`);
|
||||
const ref2 = singleRefSetter(refs, \`p\`);
|
||||
let b2;
|
||||
if (ctx['condition']) {
|
||||
b2 = block2([ref1]);
|
||||
|
||||
@@ -8,7 +8,7 @@ exports[`basics GrandChild display is controlled by its GrandParent 1`] = `
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const Comp1 = ctx['myComp'];
|
||||
return toggler(Comp1, comp1({displayGrandChild: ctx['displayGrandChild']}, key + \`__1\`, node, this, Comp1));
|
||||
return toggler(Comp1, comp1({displayGrandChild: ctx['displayGrandChild']}, (Comp1).name + key + \`__1\`, node, this, Comp1));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
@@ -1213,6 +1213,45 @@ exports[`delayed fiber does not get rendered if it was cancelled 4`] = `
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`delayed render does not go through when t-component value changed 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
const comp1 = app.createComponent(null, false, false, false, true);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const b2 = text(\`A\`);
|
||||
const Comp1 = ctx['state'].component;
|
||||
const b3 = toggler(Comp1, comp1({}, (Comp1).name + key + \`__1\`, node, this, Comp1));
|
||||
return multi([b2, b3]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`delayed render does not go through when t-component value changed 2`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const b2 = text(\`B\`);
|
||||
const b3 = text(ctx['state'].val);
|
||||
return multi([b2, b3]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`delayed render does not go through when t-component value changed 3`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
return text(\`C\`);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`delayed rendering, but then initial rendering is cancelled by yet another render 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
@@ -1776,7 +1815,7 @@ exports[`t-foreach with dynamic async component 1`] = `
|
||||
let b3;
|
||||
if (ctx['arr']) {
|
||||
const Comp1 = ctx['myComp'];
|
||||
b3 = toggler(Comp1, comp1({key: ctx['arr'][0]}, key + \`__1__\${key1}\`, node, this, Comp1));
|
||||
b3 = toggler(Comp1, comp1({key: ctx['arr'][0]}, (Comp1).name + key + \`__1__\${key1}\`, node, this, Comp1));
|
||||
}
|
||||
c_block1[i1] = withKey(multi([b3]), key1);
|
||||
}
|
||||
@@ -1810,7 +1849,7 @@ exports[`t-key on dom node having a component 1`] = `
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const tKey_1 = ctx['key'];
|
||||
const Comp1 = ctx['myComp'];
|
||||
const b2 = toggler(tKey_1, toggler(Comp1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, this, Comp1)));
|
||||
const b2 = toggler(tKey_1, toggler(Comp1, comp1({key: ctx['key']}, (Comp1).name + tKey_1 + key + \`__1\`, node, this, Comp1)));
|
||||
return toggler(tKey_1, block1([], [b2]));
|
||||
}
|
||||
}"
|
||||
@@ -1836,7 +1875,7 @@ exports[`t-key on dynamic async component (toggler is never patched) 1`] = `
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const tKey_1 = ctx['key'];
|
||||
const Comp1 = ctx['myComp'];
|
||||
return toggler(tKey_1, toggler(Comp1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, this, Comp1)));
|
||||
return toggler(tKey_1, toggler(Comp1, comp1({key: ctx['key']}, (Comp1).name + tKey_1 + key + \`__1\`, node, this, Comp1)));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
@@ -931,7 +931,7 @@ exports[`can catch errors catching error, rethrow, render parent -- a main comp
|
||||
|
||||
function slot1(ctx, node, key = \\"\\") {
|
||||
const Comp1 = ctx['cp'].Comp;
|
||||
return toggler(Comp1, comp1({}, key + \`__1\`, node, this, Comp1));
|
||||
return toggler(Comp1, comp1({}, (Comp1).name + key + \`__1\`, node, this, Comp1));
|
||||
}
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
@@ -1010,7 +1010,7 @@ exports[`can catch errors catching in child makes parent render 1`] = `
|
||||
|
||||
function slot1(ctx, node, key = \\"\\") {
|
||||
const Comp1 = ctx['elem'][1];
|
||||
return toggler(Comp1, comp1({id: ctx['elem'][0]}, key + \`__1\`, node, this, Comp1));
|
||||
return toggler(Comp1, comp1({id: ctx['elem'][0]}, (Comp1).name + key + \`__1\`, node, this, Comp1));
|
||||
}
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
|
||||
@@ -4,14 +4,15 @@ exports[`hooks autofocus hook input in a t-if 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><input block-ref=\\"0\\"/><block-child-0/></div>\`);
|
||||
let block2 = createBlock(\`<input block-ref=\\"0\\"/>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`input1\`] = el;
|
||||
const ref2 = (el) => refs[\`input2\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`input1\`);
|
||||
const ref2 = singleRefSetter(refs, \`input2\`);
|
||||
let b2;
|
||||
if (ctx['state'].flag) {
|
||||
b2 = block2([ref2]);
|
||||
@@ -25,13 +26,14 @@ exports[`hooks autofocus hook simple input 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><input block-ref=\\"0\\"/><input block-ref=\\"1\\"/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`input1\`] = el;
|
||||
const ref2 = (el) => refs[\`input2\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`input1\`);
|
||||
const ref2 = singleRefSetter(refs, \`input2\`);
|
||||
return block1([ref1, ref2]);
|
||||
}
|
||||
}"
|
||||
@@ -264,12 +266,13 @@ exports[`hooks useEffect hook effect can depend on stuff in dom 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
|
||||
let block2 = createBlock(\`<div block-ref=\\"0\\"/>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`div\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`div\`);
|
||||
let b2;
|
||||
if (ctx['state'].value) {
|
||||
b2 = block2([ref1]);
|
||||
@@ -353,12 +356,13 @@ exports[`hooks useRef hook: basic use 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><button block-ref=\\"0\\"><block-text-1/></button></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`button\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`button\`);
|
||||
let txt1 = ctx['value'];
|
||||
return block1([ref1, txt1]);
|
||||
}
|
||||
|
||||
@@ -841,6 +841,33 @@ exports[`props validation props are validated whenever component is updated 2`]
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`props validation props validation does not cause additional subscription 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
const comp1 = app.createComponent(\`Child\`, true, false, false, false);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const props1 = {obj: ctx['obj']};
|
||||
helpers.validateProps(\`Child\`, props1, this);
|
||||
const b2 = comp1(props1, key + \`__1\`, node, this, null);
|
||||
const b3 = text(ctx['obj'].otherValue);
|
||||
return multi([b2, b3]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`props validation props validation does not cause additional subscription 2`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
return text(ctx['props'].obj.value);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`props validation props: list of strings 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
|
||||
@@ -140,3 +140,39 @@ exports[`reactivity in lifecycle state changes in willUnmount do not trigger rer
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`subscriptions subscriptions returns the keys and targets observed by the component 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
return text(ctx['state'].a);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`subscriptions subscriptions returns the keys observed by the component 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
const comp1 = app.createComponent(\`Child\`, true, false, false, false);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const b2 = text(ctx['state'].a);
|
||||
const b3 = comp1({state: ctx['state']}, key + \`__1\`, node, this, null);
|
||||
return multi([b2, b3]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`subscriptions subscriptions returns the keys observed by the component 2`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
return text(ctx['props'].state.b);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
@@ -4,12 +4,13 @@ exports[`refs basic use 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div block-ref=\\"0\\"/>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`div\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`div\`);
|
||||
return block1([ref1]);
|
||||
}
|
||||
}"
|
||||
@@ -19,7 +20,7 @@ exports[`refs can use 2 refs with same name in a t-if/t-else situation 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { multiRefSetter } = helpers;
|
||||
let { singleRefSetter, multiRefSetter } = helpers;
|
||||
|
||||
let block2 = createBlock(\`<div block-ref=\\"0\\"/>\`);
|
||||
let block3 = createBlock(\`<span block-ref=\\"0\\"/>\`);
|
||||
@@ -42,13 +43,14 @@ exports[`refs refs and recursive templates 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
const comp1 = app.createComponent(\`Test\`, true, false, false, false);
|
||||
|
||||
let block1 = createBlock(\`<p block-ref=\\"0\\"><block-text-1/><block-child-0/></p>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`root\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`root\`);
|
||||
let b2;
|
||||
let txt1 = ctx['props'].tree.value;
|
||||
if (ctx['props'].tree.child) {
|
||||
@@ -59,11 +61,33 @@ exports[`refs refs and recursive templates 1`] = `
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`refs refs and t-key 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { singleRefSetter } = helpers;
|
||||
|
||||
let block2 = createBlock(\`<button block-handler-0=\\"click\\"/>\`);
|
||||
let block3 = createBlock(\`<p block-ref=\\"0\\"/>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = singleRefSetter(refs, \`root\`);
|
||||
const v1 = ctx['state'];
|
||||
let hdlr1 = [()=>v1.renderId++, ctx];
|
||||
const b2 = block2([hdlr1]);
|
||||
const tKey_1 = ctx['state'].renderId;
|
||||
const b3 = toggler(tKey_1, block3([ref1]));
|
||||
return multi([b2, b3]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`refs refs are properly bound in slots 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { capture, markRaw } = helpers;
|
||||
let { capture, singleRefSetter, markRaw } = helpers;
|
||||
const comp1 = app.createComponent(\`Dialog\`, true, true, false, true);
|
||||
|
||||
let block1 = createBlock(\`<div><span class=\\"counter\\"><block-text-0/></span><block-child-0/></div>\`);
|
||||
@@ -71,7 +95,7 @@ exports[`refs refs are properly bound in slots 1`] = `
|
||||
|
||||
function slot1(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`myButton\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`myButton\`);
|
||||
let hdlr1 = [ctx['doSomething'], ctx];
|
||||
return block2([hdlr1, ref1]);
|
||||
}
|
||||
@@ -104,7 +128,7 @@ exports[`refs throws if there are 2 same refs at the same time 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { multiRefSetter } = helpers;
|
||||
let { singleRefSetter, multiRefSetter } = helpers;
|
||||
|
||||
let block2 = createBlock(\`<div block-ref=\\"0\\"/>\`);
|
||||
let block3 = createBlock(\`<span block-ref=\\"0\\"/>\`);
|
||||
|
||||
@@ -158,7 +158,7 @@ exports[`slots can render node with t-ref and Component in same slot 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { markRaw } = helpers;
|
||||
let { singleRefSetter, markRaw } = helpers;
|
||||
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
|
||||
const comp2 = app.createComponent(\`Child\`, true, true, false, true);
|
||||
|
||||
@@ -166,7 +166,7 @@ exports[`slots can render node with t-ref and Component in same slot 1`] = `
|
||||
|
||||
function slot1(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`div\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`div\`);
|
||||
const b2 = block2([ref1]);
|
||||
const b3 = comp1({}, key + \`__1\`, node, this, null);
|
||||
return multi([b2, b3]);
|
||||
@@ -282,6 +282,47 @@ exports[`slots can use t-call in default-content of t-slot 3`] = `
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`slots conditional slot 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { capture, markRaw } = helpers;
|
||||
const comp1 = app.createComponent(\`Child\`, true, true, false, true);
|
||||
|
||||
function slot1(ctx, node, key = \\"\\") {
|
||||
return text(\`blue\`);
|
||||
}
|
||||
|
||||
function slot2(ctx, node, key = \\"\\") {
|
||||
return text(\`red\`);
|
||||
}
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let slots1 = {};
|
||||
if (ctx['state'].flag) {
|
||||
const ctx1 = capture(ctx);
|
||||
slots1['abc'] = {__render: slot1.bind(this), __ctx: ctx1};
|
||||
} else {
|
||||
const ctx2 = capture(ctx);
|
||||
slots1['abc'] = {__render: slot2.bind(this), __ctx: ctx2};
|
||||
}
|
||||
return comp1({slots: markRaw(slots1)}, key + \`__1\`, node, this, null);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`slots conditional slot 2`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { callSlot } = helpers;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
return callSlot(ctx, node, key, 'abc', false, {});
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`slots content is the default slot (variation) 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
@@ -1435,7 +1476,8 @@ exports[`slots simple default slot 1`] = `
|
||||
}
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
return comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx}})}, key + \`__1\`, node, this, null);
|
||||
let slots1 = markRaw({'default': {__render: slot1.bind(this), __ctx: ctx}});
|
||||
return comp1({slots: slots1}, key + \`__1\`, node, this, null);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@@ -1534,7 +1576,8 @@ exports[`slots simple default slot, variation 1`] = `
|
||||
}
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
return comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx}})}, key + \`__1\`, node, this, null);
|
||||
let slots1 = markRaw({'default': {__render: slot1.bind(this), __ctx: ctx}});
|
||||
return comp1({slots: slots1}, key + \`__1\`, node, this, null);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@@ -2841,16 +2884,23 @@ exports[`slots t-set-slot=default has priority over rest of the content 1`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { capture, markRaw } = helpers;
|
||||
let { markRaw, capture } = helpers;
|
||||
const comp1 = app.createComponent(\`Child\`, true, true, false, true);
|
||||
|
||||
function slot1(ctx, node, key = \\"\\") {
|
||||
const b2 = text(\` some text \`);
|
||||
const ctx2 = capture(ctx);
|
||||
return multi([b2]);
|
||||
}
|
||||
|
||||
function slot2(ctx, node, key = \\"\\") {
|
||||
return text(\`some other text\`);
|
||||
}
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const ctx1 = capture(ctx);
|
||||
return comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
|
||||
let slots1 = markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}});
|
||||
return comp1({slots: slots1}, key + \`__1\`, node, this, null);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
@@ -534,7 +534,7 @@ exports[`t-call t-call-context: ComponentNode is not looked up in the context 2`
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||
let { bind, capture, isBoundary, withDefault, setContextValue, markRaw } = helpers;
|
||||
let { singleRefSetter, bind, capture, isBoundary, withDefault, setContextValue, markRaw } = helpers;
|
||||
const comp1 = app.createComponent(\`Child\`, true, true, false, false);
|
||||
|
||||
let block2 = createBlock(\`<div block-ref=\\"0\\">outside slot</div>\`);
|
||||
@@ -543,7 +543,7 @@ exports[`t-call t-call-context: ComponentNode is not looked up in the context 2`
|
||||
|
||||
function slot1(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref2 = (el) => refs[\`myRef2\`] = el;
|
||||
const ref2 = singleRefSetter(refs, \`myRef2\`);
|
||||
ctx = Object.create(ctx);
|
||||
ctx[isBoundary] = 1
|
||||
const b4 = block4([ref2]);
|
||||
@@ -555,7 +555,7 @@ exports[`t-call t-call-context: ComponentNode is not looked up in the context 2`
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const refs = this.__owl__.refs;
|
||||
const ref1 = (el) => refs[\`myRef\`] = el;
|
||||
const ref1 = singleRefSetter(refs, \`myRef\`);
|
||||
const b2 = block2([ref1]);
|
||||
const ctx1 = capture(ctx);
|
||||
const b6 = comp1({prop: bind(this, ctx['method']),slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
|
||||
|
||||
@@ -10,7 +10,7 @@ exports[`t-component can switch between dynamic components without the need for
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const Comp1 = ctx['constructor'].components[ctx['state'].child];
|
||||
const b2 = toggler(Comp1, comp1({}, key + \`__1\`, node, this, Comp1));
|
||||
const b2 = toggler(Comp1, comp1({}, (Comp1).name + key + \`__1\`, node, this, Comp1));
|
||||
return block1([], [b2]);
|
||||
}
|
||||
}"
|
||||
@@ -51,7 +51,7 @@ exports[`t-component can use dynamic components (the class) if given (with diffe
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const tKey_1 = ctx['state'].child;
|
||||
const Comp1 = ctx['myComponent'];
|
||||
return toggler(tKey_1, toggler(Comp1, comp1({}, tKey_1 + key + \`__1\`, node, this, Comp1)));
|
||||
return toggler(tKey_1, toggler(Comp1, comp1({}, (Comp1).name + tKey_1 + key + \`__1\`, node, this, Comp1)));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@@ -91,7 +91,7 @@ exports[`t-component can use dynamic components (the class) if given 1`] = `
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const tKey_1 = ctx['state'].child;
|
||||
const Comp1 = ctx['myComponent'];
|
||||
return toggler(tKey_1, toggler(Comp1, comp1({}, tKey_1 + key + \`__1\`, node, this, Comp1)));
|
||||
return toggler(tKey_1, toggler(Comp1, comp1({}, (Comp1).name + tKey_1 + key + \`__1\`, node, this, Comp1)));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@@ -132,7 +132,7 @@ exports[`t-component modifying a sub widget 1`] = `
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const Comp1 = ctx['Counter'];
|
||||
const b2 = toggler(Comp1, comp1({}, key + \`__1\`, node, this, Comp1));
|
||||
const b2 = toggler(Comp1, comp1({}, (Comp1).name + key + \`__1\`, node, this, Comp1));
|
||||
return block1([], [b2]);
|
||||
}
|
||||
}"
|
||||
@@ -162,7 +162,7 @@ exports[`t-component switching dynamic component 1`] = `
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const Comp1 = ctx['Child'];
|
||||
return toggler(Comp1, comp1({}, key + \`__1\`, node, this, Comp1));
|
||||
return toggler(Comp1, comp1({}, (Comp1).name + key + \`__1\`, node, this, Comp1));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@@ -199,7 +199,7 @@ exports[`t-component t-component works in simple case 1`] = `
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const Comp1 = ctx['Child'];
|
||||
return toggler(Comp1, comp1({}, key + \`__1\`, node, this, Comp1));
|
||||
return toggler(Comp1, comp1({}, (Comp1).name + key + \`__1\`, node, this, Comp1));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
App,
|
||||
Component,
|
||||
ComponentConstructor,
|
||||
mount,
|
||||
onMounted,
|
||||
onRendered,
|
||||
@@ -4067,6 +4068,64 @@ test("renderings, destruction, patch, stuff, ... yet another variation", async (
|
||||
expect(fixture.innerHTML).toBe("ABD<p>2</p>");
|
||||
});
|
||||
|
||||
test("delayed render does not go through when t-component value changed", async () => {
|
||||
class C extends Component {
|
||||
static template = xml`C`;
|
||||
setup() {
|
||||
useLogLifecycle("", true);
|
||||
}
|
||||
}
|
||||
|
||||
class B extends Component {
|
||||
static template = xml`B<t t-esc="state.val"/>`;
|
||||
state = useState({ val: 1 });
|
||||
setup() {
|
||||
useLogLifecycle("", true);
|
||||
b = this;
|
||||
}
|
||||
}
|
||||
let b: B;
|
||||
|
||||
class A extends Component {
|
||||
static template = xml`A<t t-component="state.component"/>`;
|
||||
state: { component: ComponentConstructor } = useState({ component: B });
|
||||
setup() {
|
||||
useLogLifecycle("", true);
|
||||
}
|
||||
}
|
||||
|
||||
const a = await mount(A, fixture);
|
||||
expect(fixture.innerHTML).toBe("AB1");
|
||||
expect([
|
||||
"A:setup",
|
||||
"A:willRender",
|
||||
"B:setup",
|
||||
"A:rendered",
|
||||
"B:willRender",
|
||||
"B:rendered",
|
||||
"B:mounted",
|
||||
"A:mounted",
|
||||
]).toBeLogged();
|
||||
// start a render in B
|
||||
b!.state.val = 2;
|
||||
// start a render in A, invalidating the scheduled render of B, which could crash if executed.
|
||||
a.state.component = C;
|
||||
await nextTick();
|
||||
expect(fixture.innerHTML).toBe("AC");
|
||||
expect([
|
||||
"A:willRender",
|
||||
"C:setup",
|
||||
"A:rendered",
|
||||
"C:willRender",
|
||||
"C:rendered",
|
||||
"A:willPatch",
|
||||
"B:willUnmount",
|
||||
"B:willDestroy",
|
||||
"C:mounted",
|
||||
"A:patched",
|
||||
]).toBeLogged();
|
||||
});
|
||||
|
||||
// test.skip("components with shouldUpdate=false", async () => {
|
||||
// const state = { p: 1, cc: 10 };
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
|
||||
import { Component, onError, xml, mount, OwlError } from "../../src";
|
||||
import { Component, onError, xml, mount, OwlError, useState } from "../../src";
|
||||
import { App, DEV_MSG } from "../../src/runtime/app";
|
||||
import { validateProps } from "../../src/runtime/template_helpers";
|
||||
import { Schema } from "../../src/runtime/validation";
|
||||
@@ -682,6 +682,29 @@ describe("props validation", () => {
|
||||
expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is missing");
|
||||
});
|
||||
|
||||
test("props validation does not cause additional subscription", async () => {
|
||||
let obj = {
|
||||
value: 1,
|
||||
otherValue: 2,
|
||||
};
|
||||
class Child extends Component {
|
||||
static props = {
|
||||
obj: { type: Object, shape: { value: Number, otherValue: Number } },
|
||||
};
|
||||
static template = xml`<t t-esc="props.obj.value"/>`;
|
||||
}
|
||||
class Parent extends Component {
|
||||
static template = xml`<Child obj="obj"/><t t-esc="obj.otherValue"/>`;
|
||||
static components = { Child };
|
||||
|
||||
obj = useState(obj);
|
||||
}
|
||||
const app = new App(Parent, { test: true });
|
||||
await app.mount(fixture);
|
||||
expect(fixture.innerHTML).toBe("12");
|
||||
expect(app.root!.subscriptions).toEqual([{ keys: ["otherValue"], target: obj }]);
|
||||
});
|
||||
|
||||
test("props are validated whenever component is updated", async () => {
|
||||
let error: Error;
|
||||
class SubComp extends Component {
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
onWillUnmount,
|
||||
useState,
|
||||
xml,
|
||||
toRaw,
|
||||
} from "../../src";
|
||||
import { makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers";
|
||||
|
||||
@@ -232,3 +233,34 @@ describe("reactivity in lifecycle", () => {
|
||||
expect(fixture.innerHTML).toBe("34");
|
||||
});
|
||||
});
|
||||
|
||||
describe("subscriptions", () => {
|
||||
test("subscriptions returns the keys and targets observed by the component", async () => {
|
||||
class Comp extends Component {
|
||||
static template = xml`<t t-esc="state.a"/>`;
|
||||
state = useState({ a: 1, b: 2 });
|
||||
}
|
||||
const comp = await mount(Comp, fixture);
|
||||
expect(fixture.innerHTML).toBe("1");
|
||||
expect(comp.__owl__.subscriptions).toEqual([{ keys: ["a"], target: toRaw(comp.state) }]);
|
||||
});
|
||||
|
||||
test("subscriptions returns the keys observed by the component", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<t t-esc="props.state.b"/>`;
|
||||
setup() {
|
||||
child = this;
|
||||
}
|
||||
}
|
||||
let child: Child;
|
||||
class Parent extends Component {
|
||||
static template = xml`<t t-esc="state.a"/><Child state="state"/>`;
|
||||
static components = { Child };
|
||||
state = useState({ a: 1, b: 2 });
|
||||
}
|
||||
const parent = await mount(Parent, fixture);
|
||||
expect(fixture.innerHTML).toBe("12");
|
||||
expect(parent.__owl__.subscriptions).toEqual([{ keys: ["a"], target: toRaw(parent.state) }]);
|
||||
expect(child!.__owl__.subscriptions).toEqual([{ keys: ["b"], target: toRaw(parent.state) }]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
import { App, Component, mount, onMounted, useRef, useState, xml } from "../../src/index";
|
||||
import {
|
||||
App,
|
||||
Component,
|
||||
mount,
|
||||
onMounted,
|
||||
onPatched,
|
||||
useRef,
|
||||
useState,
|
||||
xml,
|
||||
} from "../../src/index";
|
||||
import { logStep, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
|
||||
|
||||
snapshotEverything();
|
||||
@@ -127,4 +136,33 @@ describe("refs", () => {
|
||||
expect(fixture.innerHTML).toBe("<p>a<p>b</p></p>");
|
||||
expect(["<p>b</p>", "<p>a<p>b</p></p>"]).toBeLogged();
|
||||
});
|
||||
|
||||
test("refs and t-key", async () => {
|
||||
let el;
|
||||
class Test extends Component {
|
||||
static components = {};
|
||||
static template = xml`
|
||||
<button t-on-click="() => state.renderId++" />
|
||||
<p t-ref="root" t-key="state.renderId"/>`;
|
||||
root = useRef("root");
|
||||
state = useState({ renderId: 1 });
|
||||
|
||||
setup() {
|
||||
onMounted(() => {
|
||||
el = this.root.el;
|
||||
});
|
||||
onPatched(() => {
|
||||
el = this.root.el;
|
||||
});
|
||||
}
|
||||
}
|
||||
await mount(Test, fixture);
|
||||
|
||||
expect(el).toBe(fixture.querySelector("p"));
|
||||
const _el = el;
|
||||
fixture.querySelector("button")!.click();
|
||||
await nextTick();
|
||||
expect(el).not.toBe(_el);
|
||||
expect(el).toBe(fixture.querySelector("p"));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -62,7 +62,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("some other text");
|
||||
});
|
||||
|
||||
test("simple slot with slot scope", async () => {
|
||||
test.skip("simple slot with slot scope", async () => {
|
||||
let child: any;
|
||||
class Child extends Component {
|
||||
static template = xml`<span><t t-slot="slotName" bool="state.bool"/></span>`;
|
||||
@@ -91,7 +91,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<span>other text</span>");
|
||||
});
|
||||
|
||||
test("slot with slot scope and t-props", async () => {
|
||||
test.skip("slot with slot scope and t-props", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`
|
||||
<t t-slot="slotName" t-props="info"/>`;
|
||||
@@ -113,7 +113,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<p>1</p><p>2</p>");
|
||||
});
|
||||
|
||||
test("simple dynamic slot with slot scope", async () => {
|
||||
test.skip("simple dynamic slot with slot scope", async () => {
|
||||
let child: any;
|
||||
class Child extends Component {
|
||||
static template = xml`<span><t t-slot="{{ 'slotName' }}" bool="state.bool"/></span>`;
|
||||
@@ -142,7 +142,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<span>other text</span>");
|
||||
});
|
||||
|
||||
test("simple named and empty slot", async () => {
|
||||
test.skip("simple named and empty slot", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<span><t t-slot="default" /><t t-slot="myEmptySlot"/></span>`;
|
||||
|
||||
@@ -160,7 +160,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<span>some text</span>");
|
||||
});
|
||||
|
||||
test("simple named and empty slot -- 2", async () => {
|
||||
test.skip("simple named and empty slot -- 2", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<span><t t-slot="myEmptySlot">default empty</t></span>`;
|
||||
|
||||
@@ -179,7 +179,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<span>default empty</span>");
|
||||
});
|
||||
|
||||
test("default slot with slot scope: shorthand syntax", async () => {
|
||||
test.skip("default slot with slot scope: shorthand syntax", async () => {
|
||||
let child: any;
|
||||
class Child extends Component {
|
||||
static template = xml`<span><t t-slot="default" bool="state.bool"/></span>`;
|
||||
@@ -206,7 +206,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<span>other text</span>");
|
||||
});
|
||||
|
||||
test("simple default slot with params", async () => {
|
||||
test.skip("simple default slot with params", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<span><t t-slot="default" bool="state.bool"/></span>`;
|
||||
state = useState({ bool: true });
|
||||
@@ -230,7 +230,7 @@ describe("slots", () => {
|
||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test("simple default slot with params and bound function", async () => {
|
||||
test.skip("simple default slot with params and bound function", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<t t-slot="default" fn.bind="getValue"/>`;
|
||||
state = useState({ value: 123 });
|
||||
@@ -249,7 +249,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("123");
|
||||
});
|
||||
|
||||
test("default slot with params with - in it", async () => {
|
||||
test.skip("default slot with params with - in it", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<t t-slot="default" some-value="state.value"/>`;
|
||||
state = useState({ value: 123 });
|
||||
@@ -265,7 +265,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("123");
|
||||
});
|
||||
|
||||
test("fun: two calls to the same slot", async () => {
|
||||
test.skip("fun: two calls to the same slot", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<t t-slot="default"/><t t-slot="default"/>`;
|
||||
}
|
||||
@@ -279,7 +279,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("some textsome text");
|
||||
});
|
||||
|
||||
test("slot content is bound to caller", async () => {
|
||||
test.skip("slot content is bound to caller", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<span><t t-slot="default"/></span>`;
|
||||
}
|
||||
@@ -299,7 +299,7 @@ describe("slots", () => {
|
||||
expect(parent.state.value).toBe(1);
|
||||
});
|
||||
|
||||
test("slot content is bound to caller (variation)", async () => {
|
||||
test.skip("slot content is bound to caller (variation)", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<span><t t-slot="default"/></span>`;
|
||||
}
|
||||
@@ -326,7 +326,7 @@ describe("slots", () => {
|
||||
expect(parent.state.value).toBe(1);
|
||||
});
|
||||
|
||||
test("can define and call slots", async () => {
|
||||
test.skip("can define and call slots", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`
|
||||
<div>
|
||||
@@ -352,7 +352,7 @@ describe("slots", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("can define and call slots with params", async () => {
|
||||
test.skip("can define and call slots with params", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`
|
||||
<div>
|
||||
@@ -381,7 +381,7 @@ describe("slots", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("can define and call slots with bound params", async () => {
|
||||
test.skip("can define and call slots with bound params", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`
|
||||
<t t-slot="abc"/>
|
||||
@@ -405,7 +405,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("abc444");
|
||||
});
|
||||
|
||||
test("no named slot content => just no children", async () => {
|
||||
test.skip("no named slot content => just no children", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`<span><t t-slot="header"/></span>`;
|
||||
}
|
||||
@@ -418,7 +418,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<span></span>");
|
||||
});
|
||||
|
||||
test("named slots can define a default content", async () => {
|
||||
test.skip("named slots can define a default content", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`
|
||||
<span>
|
||||
@@ -434,7 +434,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span>default content</span></div>");
|
||||
});
|
||||
|
||||
test("can define a default content", async () => {
|
||||
test.skip("can define a default content", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`
|
||||
<span>
|
||||
@@ -450,7 +450,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span>default content</span></div>");
|
||||
});
|
||||
|
||||
test("default content is not rendered if slot is provided", async () => {
|
||||
test.skip("default content is not rendered if slot is provided", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`
|
||||
<span>
|
||||
@@ -466,7 +466,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span>hey</span></div>");
|
||||
});
|
||||
|
||||
test("default content is not rendered if named slot is provided", async () => {
|
||||
test.skip("default content is not rendered if named slot is provided", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`
|
||||
<span>
|
||||
@@ -482,7 +482,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span>hey</span></div>");
|
||||
});
|
||||
|
||||
test("slots are properly bound to correct component", async () => {
|
||||
test.skip("slots are properly bound to correct component", async () => {
|
||||
let child: any = null;
|
||||
class Child extends Component {
|
||||
// t-set t-value in template is to force compiler to protect the scope
|
||||
@@ -518,7 +518,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<button>2</button>");
|
||||
});
|
||||
|
||||
test("slots are rendered with proper context", async () => {
|
||||
test.skip("slots are rendered with proper context", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`<span><t t-slot="footer"/></span>`;
|
||||
}
|
||||
@@ -554,7 +554,7 @@ describe("slots", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("slots are rendered with proper context, part 2", async () => {
|
||||
test.skip("slots are rendered with proper context, part 2", async () => {
|
||||
class Link extends Component {
|
||||
static template = xml`
|
||||
<a t-att-href="props.to">
|
||||
@@ -593,7 +593,7 @@ describe("slots", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("slots are rendered with proper context, part 3", async () => {
|
||||
test.skip("slots are rendered with proper context, part 3", async () => {
|
||||
class Link extends Component {
|
||||
static template = xml`
|
||||
<a t-att-href="props.to">
|
||||
@@ -632,7 +632,7 @@ describe("slots", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("slots are rendered with proper context, part 4", async () => {
|
||||
test.skip("slots are rendered with proper context, part 4", async () => {
|
||||
class Link extends Component {
|
||||
static template = xml`
|
||||
<a t-att-href="props.to">
|
||||
@@ -660,7 +660,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe('<div><a href="/user/1">User David</a></div>');
|
||||
});
|
||||
|
||||
test("content is the default slot", async () => {
|
||||
test.skip("content is the default slot", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`<div><t t-slot="default"/></div>`;
|
||||
}
|
||||
@@ -678,7 +678,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><div><span>sts rocks</span></div></div>");
|
||||
});
|
||||
|
||||
test("content is the default slot (variation)", async () => {
|
||||
test.skip("content is the default slot (variation)", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`<t t-slot="default"/>`;
|
||||
}
|
||||
@@ -694,7 +694,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<span>sts rocks</span>");
|
||||
});
|
||||
|
||||
test("default slot work with text nodes", async () => {
|
||||
test.skip("default slot work with text nodes", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`<div><t t-slot="default"/></div>`;
|
||||
}
|
||||
@@ -710,7 +710,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><div>sts rocks</div></div>");
|
||||
});
|
||||
|
||||
test("default slot work with text nodes (variation)", async () => {
|
||||
test.skip("default slot work with text nodes (variation)", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`<t t-slot="default"/>`;
|
||||
}
|
||||
@@ -723,7 +723,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("sts rocks");
|
||||
});
|
||||
|
||||
test("multiple roots are allowed in a named slot", async () => {
|
||||
test.skip("multiple roots are allowed in a named slot", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`<div><t t-slot="content"/></div>`;
|
||||
}
|
||||
@@ -744,7 +744,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><div><span>sts</span><span>rocks</span></div></div>");
|
||||
});
|
||||
|
||||
test("multiple roots are allowed in a default slot", async () => {
|
||||
test.skip("multiple roots are allowed in a default slot", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`<div><t t-slot="default"/></div>`;
|
||||
}
|
||||
@@ -763,7 +763,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><div><span>sts</span><span>rocks</span></div></div>");
|
||||
});
|
||||
|
||||
test("missing slots are ignored", async () => {
|
||||
test.skip("missing slots are ignored", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`
|
||||
<span>
|
||||
@@ -782,7 +782,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span><span>some content</span></span></div>");
|
||||
});
|
||||
|
||||
test("t-debug on a t-set-slot (defining a slot)", async () => {
|
||||
test.skip("t-debug on a t-set-slot (defining a slot)", async () => {
|
||||
const consoleLog = console.log;
|
||||
console.log = jest.fn();
|
||||
|
||||
@@ -802,7 +802,7 @@ describe("slots", () => {
|
||||
console.log = consoleLog;
|
||||
});
|
||||
|
||||
test("slot preserves properly parented relationship", async () => {
|
||||
test.skip("slot preserves properly parented relationship", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<t t-slot="default"/>`;
|
||||
}
|
||||
@@ -832,7 +832,7 @@ describe("slots", () => {
|
||||
expect(childrenChildren[0]).toBeInstanceOf(GrandChild);
|
||||
});
|
||||
|
||||
test("slot preserves properly parented relationship, even through t-call", async () => {
|
||||
test.skip("slot preserves properly parented relationship, even through t-call", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<t t-slot="default"/>`;
|
||||
}
|
||||
@@ -870,7 +870,7 @@ describe("slots", () => {
|
||||
expect(childrenChildren[0]).toBeInstanceOf(GrandChild);
|
||||
});
|
||||
|
||||
test("t-slot scope context", async () => {
|
||||
test.skip("t-slot scope context", async () => {
|
||||
expect.assertions(4);
|
||||
|
||||
class Wrapper extends Component {
|
||||
@@ -916,7 +916,7 @@ describe("slots", () => {
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
test("t-slot in recursive templates", async () => {
|
||||
test.skip("t-slot in recursive templates", async () => {
|
||||
class Wrapper extends Component {
|
||||
static template = xml`
|
||||
<wrapper>
|
||||
@@ -979,7 +979,7 @@ describe("slots", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("t-slot within dynamic t-call", async () => {
|
||||
test.skip("t-slot within dynamic t-call", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<div class="child"/>`;
|
||||
}
|
||||
@@ -1021,7 +1021,7 @@ describe("slots", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("slots in t-foreach in t-foreach", async () => {
|
||||
test.skip("slots in t-foreach in t-foreach", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`
|
||||
<div><t t-slot="default" /></div>
|
||||
@@ -1084,7 +1084,7 @@ describe("slots", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("default slot next to named slot, with default content", async () => {
|
||||
test.skip("default slot next to named slot, with default content", async () => {
|
||||
class Dialog extends Component {
|
||||
// We're using 2 slots here: a "default" one and a "footer",
|
||||
// both having default children nodes.
|
||||
@@ -1125,7 +1125,7 @@ describe("slots", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("dynamic t-slot call", async () => {
|
||||
test.skip("dynamic t-slot call", async () => {
|
||||
class Toggler extends Component {
|
||||
static template = xml`<button t-on-click="toggle"><t t-slot="{{current.slot}}"/></button>`;
|
||||
current = useState({ slot: "slot1" });
|
||||
@@ -1156,7 +1156,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><button><p>slot1</p><span>content</span></button></div>");
|
||||
});
|
||||
|
||||
test("dynamic t-slot call with default", async () => {
|
||||
test.skip("dynamic t-slot call with default", async () => {
|
||||
class Toggler extends Component {
|
||||
static template = xml`
|
||||
<button t-on-click="toggle">
|
||||
@@ -1188,7 +1188,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><button><h1>slot2</h1></button></div>");
|
||||
});
|
||||
|
||||
test("slot are properly rendered if inner props are changed", async () => {
|
||||
test.skip("slot are properly rendered if inner props are changed", async () => {
|
||||
class SomeComponent extends Component {
|
||||
static template = xml`
|
||||
<div>
|
||||
@@ -1222,7 +1222,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><button>Inc[5]</button><div><div> SC:5</div></div></div>");
|
||||
});
|
||||
|
||||
test("slots and wrapper components", async () => {
|
||||
test.skip("slots and wrapper components", async () => {
|
||||
class Link extends Component {
|
||||
static template = xml`
|
||||
<a href="abc">
|
||||
@@ -1240,7 +1240,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe(`<a href="abc">hey</a>`);
|
||||
});
|
||||
|
||||
test("template can just return a slot", async () => {
|
||||
test.skip("template can just return a slot", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<span><t t-esc="props.value"/></span>`;
|
||||
}
|
||||
@@ -1265,7 +1265,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span>5</span></div>");
|
||||
});
|
||||
|
||||
test("multiple slots containing components", async () => {
|
||||
test.skip("multiple slots containing components", async () => {
|
||||
class C extends Component {
|
||||
static template = xml`<span><t t-esc="props.val"/></span>`;
|
||||
}
|
||||
@@ -1286,7 +1286,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe(`<div><span>1</span><span>2</span></div>`);
|
||||
});
|
||||
|
||||
test("slots in t-foreach and re-rendering", async () => {
|
||||
test.skip("slots in t-foreach and re-rendering", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<span><t t-esc="state.val"/><t t-slot="default"/></span>`;
|
||||
state = useState({ val: "A" });
|
||||
@@ -1312,7 +1312,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span>B0</span><span>B1</span></div>");
|
||||
});
|
||||
|
||||
test("slots in t-foreach with t-set and re-rendering", async () => {
|
||||
test.skip("slots in t-foreach with t-set and re-rendering", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`
|
||||
<span>
|
||||
@@ -1344,7 +1344,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span>B0</span><span>B1</span></div>");
|
||||
});
|
||||
|
||||
test("nested slots in same template", async () => {
|
||||
test.skip("nested slots in same template", async () => {
|
||||
let child: any = null;
|
||||
let child2: any = null;
|
||||
let child3: any = null;
|
||||
@@ -1398,7 +1398,7 @@ describe("slots", () => {
|
||||
expect(children(parent)).toEqual([child]);
|
||||
});
|
||||
|
||||
test("t-slot nested within another slot", async () => {
|
||||
test.skip("t-slot nested within another slot", async () => {
|
||||
let portal: any = null;
|
||||
let modal: any = null;
|
||||
let child3: any = null;
|
||||
@@ -1451,7 +1451,7 @@ describe("slots", () => {
|
||||
expect(children(modal)[0]).toBe(portal);
|
||||
});
|
||||
|
||||
test("slots in slots, with vars", async () => {
|
||||
test.skip("slots in slots, with vars", async () => {
|
||||
class B extends Component {
|
||||
static template = xml`<span><t t-slot="default"/></span>`;
|
||||
}
|
||||
@@ -1480,7 +1480,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><div><span><p>heyaaron</p></span></div></div>");
|
||||
});
|
||||
|
||||
test("t-set t-value in a slot", async () => {
|
||||
test.skip("t-set t-value in a slot", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`
|
||||
<span>
|
||||
@@ -1502,7 +1502,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span>dash</span></div>");
|
||||
});
|
||||
|
||||
test("slot and t-esc", async () => {
|
||||
test.skip("slot and t-esc", async () => {
|
||||
class Dialog extends Component {
|
||||
static template = xml`<span><t t-slot="default"/></span>`;
|
||||
}
|
||||
@@ -1515,7 +1515,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span>toph</span></div>");
|
||||
});
|
||||
|
||||
test("slot and t-call", async () => {
|
||||
test.skip("slot and t-call", async () => {
|
||||
let sokka = xml`<p>sokka</p>`;
|
||||
class Dialog extends Component {
|
||||
static template = xml`<span><t t-slot="default"/></span>`;
|
||||
@@ -1529,7 +1529,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span><p>sokka</p></span></div>");
|
||||
});
|
||||
|
||||
test("slot and (inline) t-call", async () => {
|
||||
test.skip("slot and (inline) t-call", async () => {
|
||||
let sokka = xml`<p>sokka</p>`;
|
||||
class Dialog extends Component {
|
||||
static template = xml`<span><t t-slot="default"/></span>`;
|
||||
@@ -1543,7 +1543,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span><p>sokka</p></span></div>");
|
||||
});
|
||||
|
||||
test("nested slots: evaluation context and parented relationship", async () => {
|
||||
test.skip("nested slots: evaluation context and parented relationship", async () => {
|
||||
let slot: any = null;
|
||||
let grandChild: any = null;
|
||||
|
||||
@@ -1578,7 +1578,7 @@ describe("slots", () => {
|
||||
expect(children(grandChild)).toEqual([slot]);
|
||||
});
|
||||
|
||||
test("named slot inside slot", async () => {
|
||||
test.skip("named slot inside slot", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`
|
||||
<div>
|
||||
@@ -1608,7 +1608,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><div><p>Ablip</p><div><p>Bblip</p></div></div></div>");
|
||||
});
|
||||
|
||||
test("named slots inside slot, again", async () => {
|
||||
test.skip("named slots inside slot, again", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`
|
||||
<child>
|
||||
@@ -1641,7 +1641,7 @@ describe("slots", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("named slot inside slot, part 3", async () => {
|
||||
test.skip("named slot inside slot, part 3", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`
|
||||
<div>
|
||||
@@ -1673,7 +1673,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><div><p>Ablip</p><div><p>Bblip</p></div></div></div>");
|
||||
});
|
||||
|
||||
test("can render only empty slot", async () => {
|
||||
test.skip("can render only empty slot", async () => {
|
||||
class Parent extends Component {
|
||||
static template = xml`<t t-slot="default"/>`;
|
||||
}
|
||||
@@ -1688,7 +1688,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toEqual("");
|
||||
});
|
||||
|
||||
test("can render node with t-ref and Component in same slot", async () => {
|
||||
test.skip("can render node with t-ref and Component in same slot", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<t t-slot="default"/>`;
|
||||
}
|
||||
@@ -1706,7 +1706,7 @@ describe("slots", () => {
|
||||
expect(error).toBeNull();
|
||||
});
|
||||
|
||||
test("can use t-call in default-content of t-slot", async () => {
|
||||
test.skip("can use t-call in default-content of t-slot", async () => {
|
||||
const template = xml``;
|
||||
class Child extends Component {
|
||||
static template = xml`<t t-slot="default"><t t-call="${template}"/></t>`;
|
||||
@@ -1719,7 +1719,7 @@ describe("slots", () => {
|
||||
await mount(Parent, fixture);
|
||||
});
|
||||
|
||||
test("can use component in default-content of t-slot", async () => {
|
||||
test.skip("can use component in default-content of t-slot", async () => {
|
||||
class GrandChild extends Component {
|
||||
static template = xml``;
|
||||
}
|
||||
@@ -1735,7 +1735,7 @@ describe("slots", () => {
|
||||
await mount(Parent, fixture);
|
||||
});
|
||||
|
||||
test("slot content has different key from other content -- static slot", async () => {
|
||||
test.skip("slot content has different key from other content -- static slot", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<div t-esc="props.parent" />`;
|
||||
}
|
||||
@@ -1757,7 +1757,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div>SlotDisplay</div><div>Parent</div>");
|
||||
});
|
||||
|
||||
test("slot content has different key from other content -- dynamic slot", async () => {
|
||||
test.skip("slot content has different key from other content -- dynamic slot", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<div t-esc="props.parent" />`;
|
||||
}
|
||||
@@ -1780,7 +1780,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<div>SlotDisplay</div><div>Parent</div>");
|
||||
});
|
||||
|
||||
test("mix of slots, t-call, t-call with body, and giving own props child", async () => {
|
||||
test.skip("mix of slots, t-call, t-call with body, and giving own props child", async () => {
|
||||
expect.assertions(11);
|
||||
|
||||
class C extends Component {
|
||||
@@ -1836,7 +1836,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("<button>inc</button>[B][C][A][sub1] [sub2334]");
|
||||
});
|
||||
|
||||
test("slot in multiple locations", async () => {
|
||||
test.skip("slot in multiple locations", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<div>child</div>`;
|
||||
}
|
||||
@@ -1869,7 +1869,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe(" hello <div>child</div>");
|
||||
});
|
||||
|
||||
test("dynamic slot in multiple locations", async () => {
|
||||
test.skip("dynamic slot in multiple locations", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<div>child</div>`;
|
||||
}
|
||||
@@ -1902,7 +1902,7 @@ describe("slots", () => {
|
||||
expect(fixture.innerHTML).toBe("hello <div>child</div>");
|
||||
});
|
||||
|
||||
test("slot in t-foreach locations", async () => {
|
||||
test.skip("slot in t-foreach locations", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<div>child</div>`;
|
||||
}
|
||||
@@ -1933,4 +1933,33 @@ describe("slots", () => {
|
||||
"<p>1 hello <div>child</div></p><p>2 hello <div>child</div></p>"
|
||||
);
|
||||
});
|
||||
|
||||
test.skip("conditional slot", async () => {
|
||||
class Child extends Component {
|
||||
static template = xml`<t t-slot="abc"/>`;
|
||||
}
|
||||
|
||||
class Parent extends Component {
|
||||
static template = xml`
|
||||
<Child>
|
||||
<t t-if="state.flag">
|
||||
<t t-set-slot="abc">blue</t>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-set-slot="abc">red</t>
|
||||
</t>
|
||||
</Child>`;
|
||||
static components = { Child };
|
||||
state = useState({ flag: true});
|
||||
}
|
||||
const parent = await mount(Parent, fixture);
|
||||
|
||||
expect(fixture.innerHTML).toBe("blue");
|
||||
|
||||
parent.state.flag = false;
|
||||
await nextTick();
|
||||
expect(fixture.innerHTML).toBe("red");
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user