Compare commits

..

1 Commits

Author SHA1 Message Date
Samuel Degueldre abd2b42307 [IMP] slots: make defaultContent of slot available to slot as zero
In some cases, it is useful for a slot to be able to keep the default
content of the slot it is supposed to replace and simply add extra
content instead of simply replacing it entirely. This commit makes the
default content of a slot available in the context as `zero` similar to
how t-call can access the content that was inside the t-call.
2023-01-09 10:50:57 +01:00
50 changed files with 700 additions and 7066 deletions
-47
View File
@@ -1,47 +0,0 @@
{
"env": {
"browser": true,
"node": true,
"es2022": true
},
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"parserOptions": {
"sourceType": "module"
},
"root": true,
"rules": {
"no-restricted-globals": ["error", "event", "self"],
"no-const-assign": ["error"],
"no-debugger": ["error"],
"no-dupe-class-members": ["error"],
"no-dupe-keys": ["error"],
"no-dupe-args": ["error"],
"no-dupe-else-if": ["error"],
"no-unsafe-negation": ["error"],
"no-duplicate-imports": ["error"],
"valid-typeof": ["error"],
"@typescript-eslint/no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": false, "caughtErrors": "all" }],
"no-restricted-syntax": [
"error",
{
"selector": "MemberExpression[object.name='test'][property.name='only']",
"message": "test.only(...) is forbidden",
},
{
"selector": "MemberExpression[object.name='describe'][property.name='only']",
"message": "describe.only(...) is forbidden",
}
],
},
"globals": {
"describe": true,
"expect": true,
"test": true,
"beforeEach": true,
"beforeAll": true,
"afterEach": true,
"afterAll": true,
"jest": true,
},
}
+1 -2
View File
@@ -22,8 +22,7 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm install
- run: npm run test
- run: npm run check-formatting
- run: npm run lint
- run: npm run build
+3 -1
View File
@@ -14,6 +14,9 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
yarn.lock
#ide's
.vscode
.idea
@@ -22,7 +25,6 @@ node_modules
# Extras temp file
/tools/owl.js
/tools/devtools/build
release-notes.md
+3 -3
View File
@@ -174,9 +174,9 @@ class Root extends Component {
```
The template contains a [`t-foreach`](../reference/templates.md#loops) loop to iterate
through the tasks. It can find the `tasks` list from the component, since the rendering
context contains the properties of the component. Note that we use the `id` of each task
as a `t-key`, which is very common. There are two css classes: `task-list` and `task`,
through the tasks. It can find the `tasks` list from the component, since the
component is the rendering context. Note that we use the `id` of each task as a
`t-key`, which is very common. There are two css classes: `task-list` and `task`,
that we will use in the next section.
Finally, notice the use of the `t-att-checked` attribute:
+4 -3
View File
@@ -115,7 +115,7 @@ It is useful to explain the various rules that apply on these expressions:
<div><p t-if="console.log(1)">NOT valid</p></div>
```
2. it can use anything in the rendering context (which typically contains the properties of the component):
2. it can use anything in the rendering context (typically, the component):
```xml
<p t-if="user.birthday === today()">Happy bithday!</p>
@@ -541,8 +541,9 @@ This can be used to define variables scoped to a sub template:
```
Note: by default, the rendering context for a sub template is simply the current
rendering context. However, it may be useful to be able to specify a specific
object as context. This can be done by using the `t-call-context` directive:
rendering context (so, the current component). However, it may be useful to be
able to specify a specific object as context. This can be done by using the
`t-call-context` directive:
```xml
<t t-call="other-template" t-call-context="obj"/>
-5711
View File
File diff suppressed because it is too large Load Diff
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@odoo/owl",
"version": "2.0.7",
"version": "2.0.2",
"description": "Odoo Web Library (OWL)",
"main": "dist/owl.cjs.js",
"module": "dist/owl.es.js",
@@ -25,7 +25,6 @@
"playground:watch": "npm-run-all --parallel playground:serve \"build:* -- --watch\"",
"prettier": "prettier {src/*.ts,src/**/*.ts,tests/*.ts,tests/**/*.ts,doc/*.md,doc/**/*.md} --write",
"check-formatting": "prettier {src/*.ts,src/**/*.ts,tests/*.ts,tests/**/*.ts,doc/*.md,doc/**/*.md} --check",
"lint": "eslint src/**/*.ts tests/**/*.ts",
"publish": "npm run build && npm publish",
"release": "node tools/release.js",
"compile_templates": "node tools/compile_xml.js"
@@ -43,25 +42,26 @@
"devDependencies": {
"@types/jest": "^27.0.1",
"@types/node": "^14.11.8",
"@typescript-eslint/eslint-plugin": "5.48.1",
"@typescript-eslint/parser": "5.48.1",
"chalk": "^3.0.0",
"cpx": "^1.5.0",
"current-git-branch": "^1.1.0",
"eslint": "8.31.0",
"git-rev-sync": "^3.0.2",
"git-rev-sync": "^1.12.0",
"github-api": "^3.3.0",
"jest": "^27.1.0",
"jest-diff": "^27.3.1",
"jest-environment-jsdom": "^27.1.0",
"live-server": "^1.2.1",
"npm-run-all": "^4.1.5",
"prettier": "2.4.1",
"rollup": "^2.56.3",
"rollup-plugin-dts": "^4.2.2",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.31.1",
"sass": "^1.16.1",
"source-map-support": "^0.5.10",
"ts-jest": "^27.0.5",
"typescript": "4.5.2"
"typescript": "4.5.2",
"uglify-es": "^3.3.9"
},
"jest": {
"testEnvironment": "jsdom",
+14 -61
View File
@@ -1,3 +1,4 @@
import { isProp } from "../runtime/blockdom/attributes";
import {
compileExpr,
compileExprToArray,
@@ -57,30 +58,6 @@ function generateId(prefix: string = "") {
return prefix + nextDataIds[prefix];
}
function isProp(tag: string, key: string): boolean {
switch (tag) {
case "input":
return (
key === "checked" ||
key === "indeterminate" ||
key === "value" ||
key === "readonly" ||
key === "readOnly" ||
key === "disabled"
);
case "option":
return key === "selected" || key === "disabled";
case "textarea":
return key === "value" || key === "readonly" || key === "readOnly" || key === "disabled";
case "select":
return key === "value" || key === "disabled";
case "button":
case "optgroup":
return key === "disabled";
}
return false;
}
// -----------------------------------------------------------------------------
// BlockDescription
// -----------------------------------------------------------------------------
@@ -601,26 +578,19 @@ export class CodeGenerator {
attrName = key === "t-att" ? null : key.slice(6);
expr = compileExpr(ast.attrs[key]);
if (attrName && isProp(ast.tag, attrName)) {
if (attrName === "readonly") {
// the property has a different name than the attribute
attrName = "readOnly";
}
// we force a new string or new boolean to bypass the equality check in blockdom when patching same value
if (attrName === "value") {
// When the expression is falsy (except 0), fall back to an empty string
expr = `new String((${expr}) === 0 ? 0 : ((${expr}) || ""))`;
// When the expression is falsy, fall back to an empty string
expr = `new String((${expr}) || "")`;
} else {
expr = `new Boolean(${expr})`;
}
const idx = block!.insertData(expr, "prop");
attrs[`block-property-${idx}`] = attrName!;
}
const idx = block!.insertData(expr, "attr");
if (key === "t-att") {
attrs[`block-attributes`] = String(idx);
} else {
const idx = block!.insertData(expr, "attr");
if (key === "t-att") {
attrs[`block-attributes`] = String(idx);
} else {
attrs[`block-attribute-${idx}`] = attrName!;
}
attrs[`block-attribute-${idx}`] = attrName!;
}
} else if (this.translatableAttributes.includes(key)) {
attrs[key] = this.translateFn(ast.attrs[key]);
@@ -662,23 +632,15 @@ export class CodeGenerator {
let idx: number;
if (specialInitTargetAttr) {
let targetExpr = targetAttr in attrs && `'${attrs[targetAttr]}'`;
if (!targetExpr && ast.attrs) {
// look at the dynamic attribute counterpart
const dynamicTgExpr = ast.attrs[`t-att-${targetAttr}`];
if (dynamicTgExpr) {
targetExpr = compileExpr(dynamicTgExpr);
}
}
idx = block!.insertData(`${fullExpression} === ${targetExpr}`, "prop");
attrs[`block-property-${idx}`] = specialInitTargetAttr;
idx = block!.insertData(`${fullExpression} === '${attrs[targetAttr]}'`, "attr");
attrs[`block-attribute-${idx}`] = specialInitTargetAttr;
} else if (hasDynamicChildren) {
const bValueId = generateId("bValue");
tModelSelectedExpr = `${bValueId}`;
this.define(tModelSelectedExpr, fullExpression);
} else {
idx = block!.insertData(`${fullExpression}`, "prop");
attrs[`block-property-${idx}`] = targetAttr;
idx = block!.insertData(`${fullExpression}`, "attr");
attrs[`block-attribute-${idx}`] = targetAttr;
}
this.helpers.add("toNumber");
let valueCode = `ev.target.${targetAttr}`;
@@ -702,9 +664,8 @@ 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(`singleRefSetter(refs, ${str})`, "ref");
const idx = block!.insertData(`(el) => refs[${str}] = el`, "ref");
attrs["block-ref"] = String(idx);
} else {
let name = ast.ref;
@@ -717,8 +678,7 @@ export class CodeGenerator {
info[1] = `multiRefSetter(refs, \`${name}\`)`;
} else {
let id = generateId("ref");
this.helpers.add("singleRefSetter");
this.target.refInfo[name] = [id, `singleRefSetter(refs, \`${name}\`)`];
this.target.refInfo[name] = [id, `(el) => refs[\`${name}\`] = el`];
const index = block!.data.push(id) - 1;
attrs["block-ref"] = String(index);
}
@@ -1255,13 +1215,6 @@ export class CodeGenerator {
})`,
});
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})`;
+1 -1
View File
@@ -28,7 +28,7 @@ import { OwlError } from "../runtime/error_handling";
//------------------------------------------------------------------------------
const RESERVED_WORDS =
"true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,eval,void,Math,RegExp,Array,Object,Date".split(
"true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,this,eval,void,Math,RegExp,Array,Object,Date".split(
","
);
+3 -20
View File
@@ -1,11 +1,12 @@
import { Component, ComponentConstructor, Props } from "./component";
import { ComponentNode } from "./component_node";
import { nodeErrorHandlers, OwlError, handleError } from "./error_handling";
import { Fiber, RootFiber, MountOptions } from "./fibers";
import { nodeErrorHandlers, OwlError } from "./error_handling";
import { Fiber, MountOptions } from "./fibers";
import { Scheduler } from "./scheduler";
import { validateProps } from "./template_helpers";
import { TemplateSet, TemplateSetConfig } from "./template_set";
import { validateTarget } from "./utils";
import { handleError } from "./error_handling";
// reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f
@@ -31,22 +32,6 @@ This is not suitable for production use.
See https://github.com/odoo/owl/blob/${hash}/doc/reference/app.md#configuration for more information.`;
};
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<
T extends abstract new (...args: any) => any = any,
P extends object = any,
@@ -64,7 +49,6 @@ export class App<
constructor(Root: ComponentConstructor<P, E>, config: AppConfig<P, E> = {}) {
super(config);
this.Root = Root;
window.__OWL_DEVTOOLS__.apps.add(this);
if (config.test) {
this.dev = true;
}
@@ -126,7 +110,6 @@ export class App<
this.scheduler.flush();
this.root.destroy();
}
window.__OWL_DEVTOOLS__.apps.delete(this);
}
createComponent<P extends Props>(
+30
View File
@@ -140,3 +140,33 @@ export function updateClass(this: HTMLElement, val: any, oldVal: any) {
}
}
}
export function makePropSetter(name: string): Setter<HTMLElement> {
return function setProp(this: HTMLElement, value: any) {
// support 0, fallback to empty string for other falsy values
(this as any)[name] = value === 0 ? 0 : value ? value.valueOf() : "";
};
}
export function isProp(tag: string, key: string): boolean {
switch (tag) {
case "input":
return (
key === "checked" ||
key === "indeterminate" ||
key === "value" ||
key === "readonly" ||
key === "disabled"
);
case "option":
return key === "selected" || key === "disabled";
case "textarea":
return key === "value" || key === "readonly" || key === "disabled";
case "select":
return key === "value" || key === "disabled";
case "button":
case "optgroup":
return key === "disabled";
}
return false;
}
+15 -29
View File
@@ -1,5 +1,13 @@
import { OwlError } from "../error_handling";
import { attrsSetter, attrsUpdater, createAttrUpdater, setClass, updateClass } from "./attributes";
import {
attrsSetter,
attrsUpdater,
createAttrUpdater,
isProp,
makePropSetter,
setClass,
updateClass,
} from "./attributes";
import { config } from "./config";
import { createEventHandler } from "./events";
import type { VNode } from "./index";
@@ -17,13 +25,6 @@ const nodeGetNextSibling = getDescriptor(nodeProto, "nextSibling").get!;
const NO_OP = () => {};
function makePropSetter(name: string): Setter<HTMLElement> {
return function setProp(this: HTMLElement, value: any) {
// support 0, fallback to empty string for other falsy values
(this as any)[name] = value === 0 ? 0 : value ? value.valueOf() : "";
};
}
// -----------------------------------------------------------------------------
// Main compiler code
// -----------------------------------------------------------------------------
@@ -100,7 +101,7 @@ function normalizeNode(node: HTMLElement | Text) {
interface DynamicInfo {
idx: number;
refIdx?: number;
type: "text" | "child" | "handler" | "attribute" | "attributes" | "property" | "ref";
type: "text" | "child" | "handler" | "attribute" | "attributes" | "ref";
isOnlyChild?: boolean;
name?: string;
tag?: string;
@@ -183,14 +184,6 @@ function buildTree(
name: attrValue,
tag: tagName,
});
} else if (attrName.startsWith("block-property-")) {
const idx = parseInt(attrName.slice(15), 10);
info.push({
type: "property",
idx,
name: attrValue,
tag: tagName,
});
} else if (attrName === "block-attributes") {
info.push({
type: "attributes",
@@ -384,22 +377,15 @@ function updateCtx(ctx: BlockCtx, tree: IntermediateTree) {
};
}
break;
case "property": {
const refIdx = info.refIdx!;
const setProp = makePropSetter(info.name!);
ctx.locations.push({
idx: info.idx,
refIdx,
setData: setProp,
updateData: setProp,
});
break;
}
case "attribute": {
const refIdx = info.refIdx!;
let updater: any;
let setter: any;
if (info.name === "class") {
if (isProp(info.tag!, info.name!)) {
const setProp = makePropSetter(info.name!);
setter = setProp;
updater = setProp;
} else if (info.name === "class") {
setter = setClass;
updater = updateClass;
} else {
+1 -3
View File
@@ -114,8 +114,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
}
}
this.component = new C(props, env, this);
const ctx = Object.assign(Object.create(this.component), { this: this.component });
this.renderFn = app.getTemplate(C.template).bind(this.component, ctx, this);
this.renderFn = app.getTemplate(C.template).bind(this.component, this.component, this);
this.component.setup();
currentNode = null;
}
@@ -318,7 +317,6 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
}
_patch() {
let hasChildren = false;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (let _k in this.children) {
hasChildren = true;
break;
+1 -1
View File
@@ -117,7 +117,7 @@ export function useEffect(effect: Effect, computeDependencies: () => any[] = ()
* `useExternalListener(window, 'click', this._doSomething);`
* */
export function useExternalListener(
target: EventTarget,
target: HTMLElement | typeof window,
eventName: string,
handler: EventListener,
eventParams?: AddEventListenerOptions
+7 -23
View File
@@ -1,13 +1,8 @@
import type { Callback } from "./utils";
import { Callback } from "./utils";
import { OwlError } from "./error_handling";
// Special key to subscribe to, to be notified of key creation/deletion
const KEYCHANGES = Symbol("Key changes");
// Used to specify the absence of a callback, can be used as WeakMap key but
// should only be used as a sentinel value and never called.
const NO_CALLBACK = () => {
throw new Error("Called NO_CALLBACK. Owl is broken, please report this to the maintainers.");
};
// The following types only exist to signify places where objects are expected
// to be reactive or not, they provide no type checking benefit over "object"
@@ -91,9 +86,6 @@ const targetToKeysToCallbacks = new WeakMap<Target, Map<PropertyKey, Set<Callbac
* @param callback the function to call when the key changes
*/
function observeTargetKey(target: Target, key: PropertyKey, callback: Callback): void {
if (callback === NO_CALLBACK) {
return;
}
if (!targetToKeysToCallbacks.get(target)) {
targetToKeysToCallbacks.set(target, new Map());
}
@@ -148,11 +140,8 @@ export function clearReactivesForCallback(callback: Callback): void {
if (!observedKeys) {
continue;
}
for (const [key, callbacks] of observedKeys.entries()) {
for (const callbacks of observedKeys.values()) {
callbacks.delete(callback);
if (!callbacks.size) {
observedKeys.delete(key);
}
}
}
targetsToClear.clear();
@@ -162,15 +151,10 @@ export function getSubscriptions(callback: Callback) {
const targets = callbacksToTargets.get(callback) || [];
return [...targets].map((target) => {
const keysToCallbacks = targetToKeysToCallbacks.get(target);
let keys = [];
if (keysToCallbacks) {
for (const [key, cbs] of keysToCallbacks) {
if (cbs.has(callback)) {
keys.push(key);
}
}
}
return { target, keys };
return {
target,
keys: keysToCallbacks ? [...keysToCallbacks.keys()] : [],
};
});
}
// Maps reactive objects to the underlying target
@@ -203,7 +187,7 @@ const reactiveCache = new WeakMap<Target, WeakMap<Callback, Reactive<Target>>>()
* reactive has changed
* @returns a proxy that tracks changes to it
*/
export function reactive<T extends Target>(target: T, callback: Callback = NO_CALLBACK): T {
export function reactive<T extends Target>(target: T, callback: Callback = () => {}): T {
if (!canBeMadeReactive(target)) {
throw new OwlError(`Cannot make the given value reactive`);
}
+7 -11
View File
@@ -29,6 +29,13 @@ function callSlot(
const slots = ctx.props.slots || {};
const { __render, __ctx, __scope } = slots[name] || {};
const slotScope = ObjectCreate(__ctx || {});
if (defaultContent) {
Object.defineProperty(slotScope, helpers.zero, {
get() {
return defaultContent(ctx, parent, key);
},
});
}
if (__scope) {
slotScope[__scope] = extra;
}
@@ -202,16 +209,6 @@ 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
@@ -270,7 +267,6 @@ export const helpers = {
prepareList,
setContextValue,
multiRefSetter,
singleRefSetter,
shallowEqual,
toNumber,
validateProps,
-2
View File
@@ -1,5 +1,4 @@
import { OwlError } from "./error_handling";
import { toRaw } from "./reactivity";
type BaseType =
| typeof String
@@ -85,7 +84,6 @@ 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) {
+56
View File
@@ -145,3 +145,59 @@ test("class attribute (with a preexisting value", async () => {
patch(tree, block([""]));
expect(fixture.innerHTML).toBe(`<div class="tomato"></div>`);
});
describe("properties", () => {
test("input with value attribute", () => {
// render input with initial value
const block = createBlock(`<input block-attribute-0="value"/>`);
const tree = block(["zucchini"]);
mount(tree, fixture);
// const bnode1 = renderToBdom(template, { v: "zucchini" });
// const fixture = makeTestFixture();
// mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.value).toBe("zucchini");
// change value manually in input, to simulate user input
input.value = "tomato";
expect(input.value).toBe("tomato");
// rerender with a different value, and patch actual dom, to check that
// input value was properly reset by owl
patch(tree, block(["potato"]));
expect(input.value).toBe("potato");
});
test("input with value attribute, and falsy value given", () => {
const block = createBlock(`<input block-attribute-0="value"/>`);
const tree = block([undefined]);
mount(tree, fixture);
const input = fixture.querySelector("input")!;
expect(input.value).toBe("");
patch(tree, block([null]));
expect(input.value).toBe("");
patch(tree, block([0]));
expect(input.value).toBe("0");
patch(tree, block([""]));
expect(input.value).toBe("");
patch(tree, block([false]));
expect(input.value).toBe("");
});
test("input type=checkbox with checked attribute", () => {
// render input with initial value
const block = createBlock(`<input type="checkbox" block-attribute-0="checked"/>`);
const tree = block([true]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe(`<input type="checkbox">`);
const input = fixture.querySelector("input")!;
expect(input.checked).toBe(true);
});
});
-70
View File
@@ -1,70 +0,0 @@
import { mount, patch, createBlock } from "../../src/runtime/blockdom";
import { makeTestFixture } from "./helpers";
//------------------------------------------------------------------------------
// Setup and helpers
//------------------------------------------------------------------------------
let fixture: HTMLElement;
beforeEach(() => {
fixture = makeTestFixture();
});
afterEach(() => {
fixture.remove();
});
test("input with value property", () => {
// render input with initial value
const block = createBlock(`<input block-property-0="value"/>`);
const tree = block(["zucchini"]);
mount(tree, fixture);
// const bnode1 = renderToBdom(template, { v: "zucchini" });
// const fixture = makeTestFixture();
// mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.value).toBe("zucchini");
// change value manually in input, to simulate user input
input.value = "tomato";
expect(input.value).toBe("tomato");
// rerender with a different value, and patch actual dom, to check that
// input value was properly reset by owl
patch(tree, block(["potato"]));
expect(input.value).toBe("potato");
});
test("input with value property, and falsy value given", () => {
const block = createBlock(`<input block-property-0="value"/>`);
const tree = block([undefined]);
mount(tree, fixture);
const input = fixture.querySelector("input")!;
expect(input.value).toBe("");
patch(tree, block([null]));
expect(input.value).toBe("");
patch(tree, block([0]));
expect(input.value).toBe("0");
patch(tree, block([""]));
expect(input.value).toBe("");
patch(tree, block([false]));
expect(input.value).toBe("");
});
test("input type=checkbox with checked property", () => {
// render input with initial value
const block = createBlock(`<input type="checkbox" block-property-0="checked"/>`);
const tree = block([true]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe(`<input type="checkbox">`);
const input = fixture.querySelector("input")!;
expect(input.checked).toBe(true);
});
@@ -28,6 +28,20 @@ exports[`attributes changing a class with t-att-class 1`] = `
}"
`;
exports[`attributes changing an attribute with t-att- 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div block-attribute-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = ctx['v'];
return block1([attr1]);
}
}"
`;
exports[`attributes class and t-att-class should combine together 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -707,6 +721,20 @@ exports[`attributes updating classes (with obj notation) 1`] = `
}"
`;
exports[`attributes updating property with falsy value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-attribute-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = new String((ctx['v']) || \\"\\");
return block1([attr1]);
}
}"
`;
exports[`attributes various escapes 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -735,3 +763,114 @@ exports[`attributes various escapes 2 1`] = `
}
}"
`;
exports[`special cases for some specific html attributes/properties input of type checkbox with t-att-indeterminate 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input type=\\"checkbox\\" block-attribute-0=\\"indeterminate\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = new Boolean(ctx['v']);
return block1([attr1]);
}
}"
`;
exports[`special cases for some specific html attributes/properties input type= checkbox, with t-att-checked 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input type=\\"checkbox\\" block-attribute-0=\\"checked\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = new Boolean(ctx['flag']);
return block1([attr1]);
}
}"
`;
exports[`special cases for some specific html attributes/properties input with t-att-value (patching with same value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-attribute-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = new String((ctx['v']) || \\"\\");
return block1([attr1]);
}
}"
`;
exports[`special cases for some specific html attributes/properties input with t-att-value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-attribute-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = new String((ctx['v']) || \\"\\");
return block1([attr1]);
}
}"
`;
exports[`special cases for some specific html attributes/properties input, type checkbox, with t-att-checked (patching with same value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input type=\\"checkbox\\" block-attribute-0=\\"checked\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = new Boolean(ctx['v']);
return block1([attr1]);
}
}"
`;
exports[`special cases for some specific html attributes/properties select with t-att-value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<select block-attribute-0=\\"value\\"><option value=\\"potato\\">Potato</option><option value=\\"tomato\\">Tomato</option><option value=\\"onion\\">Onion</option></select>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = new String((ctx['value']) || \\"\\");
return block1([attr1]);
}
}"
`;
exports[`special cases for some specific html attributes/properties textarea with t-att-value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<textarea block-attribute-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = new String((ctx['v']) || \\"\\");
return block1([attr1]);
}
}"
`;
exports[`special cases for some specific html attributes/properties various boolean html attributes 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div><input type=\\"checkbox\\" checked=\\"checked\\"/><input checked=\\"checked\\"/><div checked=\\"checked\\"/><div selected=\\"selected\\"/><option selected=\\"selected\\" other=\\"1\\"/><input readonly=\\"readonly\\"/><button disabled=\\"disabled\\"/></div>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
@@ -519,9 +519,8 @@ exports[`t-on t-on, with arguments and t-call 2`] = `
let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['this'];
const v2 = ctx['value'];
let hdlr1 = [()=>v1.update(v2), ctx];
const v1 = ctx['value'];
let hdlr1 = [()=>this.update(v1), ctx];
return block1([hdlr1]);
}
}"
+16 -16
View File
@@ -182,12 +182,12 @@ exports[`misc other complex template 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { prepareList, withKey, singleRefSetter } = helpers;
let { prepareList, withKey } = 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);
let block1 = createBlock(\`<div><header><nav class=\\"navbar navbar-expand-md navbar-light bg-light\\"><a block-attribute-0=\\"href\\"><b style=\\"color:#777;\\"><block-text-1/></b></a><button type=\\"button\\" class=\\"navbar-toggler\\" data-toggle=\\"collapse\\" data-target=\\"#top_menu_collapse\\"><span class=\\"navbar-toggler-icon\\"/></button><div class=\\"collapse navbar-collapse\\" id=\\"top_menu_collapse\\" aria-expanded=\\"false\\"><ul class=\\"nav navbar-nav ml-auto text-right\\" id=\\"top_menu\\"><block-child-0/><li class=\\"nav-item divider\\"/><block-child-1/></ul><div><div class=\\"input-group input-group-sm\\"><div class=\\"input-group-prepend input-group-sm\\"><button class=\\"btn btn-default fa fa-cog\\" title=\\"Settings\\" block-handler-2=\\"click\\"/><button class=\\"btn btn-default\\" block-handler-3=\\"click\\"> More </button><block-child-2/></div><input class=\\"form-control\\" type=\\"text\\" placeholder=\\"Search\\" aria-label=\\"Search\\" name=\\"search\\" block-property-4=\\"value\\" block-handler-5=\\"keyup\\" block-handler-6=\\"change\\" block-ref=\\"7\\"/><div class=\\"input-group-append\\"><button class=\\"btn btn-default fa fa-eraser\\" block-handler-8=\\"click\\"/></div></div></div></div></nav></header><div class=\\"container-fluid\\" block-ref=\\"9\\"><div class=\\"row\\"><!--div class=\\"form-group col-md-6\\">
let block1 = createBlock(\`<div><header><nav class=\\"navbar navbar-expand-md navbar-light bg-light\\"><a block-attribute-0=\\"href\\"><b style=\\"color:#777;\\"><block-text-1/></b></a><button type=\\"button\\" class=\\"navbar-toggler\\" data-toggle=\\"collapse\\" data-target=\\"#top_menu_collapse\\"><span class=\\"navbar-toggler-icon\\"/></button><div class=\\"collapse navbar-collapse\\" id=\\"top_menu_collapse\\" aria-expanded=\\"false\\"><ul class=\\"nav navbar-nav ml-auto text-right\\" id=\\"top_menu\\"><block-child-0/><li class=\\"nav-item divider\\"/><block-child-1/></ul><div><div class=\\"input-group input-group-sm\\"><div class=\\"input-group-prepend input-group-sm\\"><button class=\\"btn btn-default fa fa-cog\\" title=\\"Settings\\" block-handler-2=\\"click\\"/><button class=\\"btn btn-default\\" block-handler-3=\\"click\\"> More </button><block-child-2/></div><input class=\\"form-control\\" type=\\"text\\" placeholder=\\"Search\\" aria-label=\\"Search\\" name=\\"search\\" block-attribute-4=\\"value\\" block-handler-5=\\"keyup\\" block-handler-6=\\"change\\" block-ref=\\"7\\"/><div class=\\"input-group-append\\"><button class=\\"btn btn-default fa fa-eraser\\" block-handler-8=\\"click\\"/></div></div></div></div></nav></header><div class=\\"container-fluid\\" block-ref=\\"9\\"><div class=\\"row\\"><!--div class=\\"form-group col-md-6\\">
<h5>Search options</h5>
<input class=\\"form-control\\" type=\\"text\\" name=\\"default_search\\" id=\\"default_search\\" t-att-checked=\\"default_search\\" placeholder=\\"Default search\\"/>
@@ -209,8 +209,8 @@ exports[`misc other complex template 1`] = `
let block12 = createBlock(\`<li class=\\"nav-item divider\\"/>\`);
let block13 = createBlock(\`<li class=\\"nav-item dropdown\\"><a href=\\"#\\" class=\\"nav-link dropdown-toggle\\" data-toggle=\\"dropdown\\"><b><span><block-text-0/></span></b></a><div class=\\"dropdown-menu js_usermenu\\" role=\\"menu\\"><a class=\\"dropdown-item\\" id=\\"o_logout\\" role=\\"menuitem\\" block-attribute-1=\\"href\\">Logout</a><a class=\\"dropdown-item\\" role=\\"menuitem\\" block-attribute-2=\\"href\\">Web</a></div></li>\`);
let block14 = createBlock(\`<select class=\\"custom-select\\" name=\\"category\\" id=\\"category\\"><block-child-0/></select>\`);
let block16 = createBlock(\`<option block-attribute-0=\\"value\\" block-property-1=\\"selected\\"><block-text-2/></option>\`);
let block20 = createBlock(\`<div class=\\"form-check\\"><input class=\\"form-check-input\\" type=\\"checkbox\\" block-attribute-0=\\"name\\" block-attribute-1=\\"id\\" block-property-2=\\"checked\\" block-attribute-3=\\"data-trigger_id\\" block-handler-4=\\"change\\"/><label class=\\"form-check-label\\" block-attribute-5=\\"for\\"><block-text-6/></label></div>\`);
let block16 = createBlock(\`<option block-attribute-0=\\"value\\" block-attribute-1=\\"selected\\"><block-text-2/></option>\`);
let block20 = createBlock(\`<div class=\\"form-check\\"><input class=\\"form-check-input\\" type=\\"checkbox\\" block-attribute-0=\\"name\\" block-attribute-1=\\"id\\" block-attribute-2=\\"checked\\" block-attribute-3=\\"data-trigger_id\\" block-handler-4=\\"change\\"/><label class=\\"form-check-label\\" block-attribute-5=\\"for\\"><block-text-6/></label></div>\`);
let block21 = createBlock(\`<div><button class=\\"btn btn-sm btn-default\\" block-handler-0=\\"click\\">All</button><button class=\\"btn btn-sm btn-default\\" block-handler-1=\\"click\\">None</button><button class=\\"btn btn-sm btn-info\\" block-handler-2=\\"click\\">Default</button><button class=\\"btn btn-sm btn-default\\" block-handler-3=\\"click\\">Close</button></div>\`);
let block23 = createBlock(\`<div class=\\"alert alert-warning\\" role=\\"alert\\"><block-text-0/> <!-- todo fixme--></div>\`);
let block24 = createBlock(\`<div class=\\"mb32\\"><h1>No project</h1></div>\`);
@@ -218,8 +218,8 @@ exports[`misc other complex template 1`] = `
return function template(ctx, node, key = \\"\\") {
const refs = this.__owl__.refs;
const ref1 = singleRefSetter(refs, \`search_input\`);
const ref2 = singleRefSetter(refs, \`settings_menu\`);
const ref1 = (el) => refs[\`search_input\`] = el;
const ref2 = (el) => refs[\`settings_menu\`] = el;
let b2,b4,b14,b17,b22,b23,b24,b25;
let attr1 = \`/runbot/\${ctx['project'].slug}\`;
let txt1 = ctx['project'].name;
@@ -269,15 +269,15 @@ exports[`misc other complex template 1`] = `
ctx[\`category\`] = v_block15[i1];
const key1 = ctx['category'].id;
let attr6 = ctx['category'].id;
let prop1 = new Boolean(ctx['category'].id==ctx['options'].active_category_id);
let attr7 = new Boolean(ctx['category'].id==ctx['options'].active_category_id);
let txt5 = ctx['category'].name;
c_block15[i1] = withKey(block16([attr6, prop1, txt5]), key1);
c_block15[i1] = withKey(block16([attr6, attr7, txt5]), key1);
}
ctx = ctx.__proto__;
const b15 = list(c_block15);
b14 = block14([], [b15]);
}
let prop2 = new String((ctx['search'].value) === 0 ? 0 : ((ctx['search'].value) || \\"\\"));
let attr8 = new String((ctx['search'].value) || \\"\\");
let hdlr4 = [ctx['updateFilter'], ctx];
let hdlr5 = [ctx['updateFilter'], ctx];
let hdlr6 = [ctx['clearSearch'], ctx];
@@ -289,14 +289,14 @@ exports[`misc other complex template 1`] = `
const key1 = ctx['trigger'].id;
let b20;
if (!ctx['trigger'].manual&&ctx['trigger'].project_id===ctx['project'].id&&ctx['trigger'].category_id===ctx['options'].active_category_id) {
let attr7 = \`trigger_\${ctx['trigger'].id}\`;
let attr8 = \`trigger_\${ctx['trigger'].id}\`;
let prop3 = new Boolean(ctx['options'].trigger_display[ctx['trigger'].id]);
let attr9 = ctx['trigger'].id;
let hdlr7 = [ctx['updateTriggerDisplay'], ctx];
let attr9 = \`trigger_\${ctx['trigger'].id}\`;
let attr10 = \`trigger_\${ctx['trigger'].id}\`;
let attr11 = new Boolean(ctx['options'].trigger_display[ctx['trigger'].id]);
let attr12 = ctx['trigger'].id;
let hdlr7 = [ctx['updateTriggerDisplay'], ctx];
let attr13 = \`trigger_\${ctx['trigger'].id}\`;
let txt6 = ctx['trigger'].name;
b20 = block20([attr7, attr8, prop3, attr9, hdlr7, attr10, txt6]);
b20 = block20([attr9, attr10, attr11, attr12, hdlr7, attr13, txt6]);
}
c_block18[i1] = withKey(multi([b20]), key1);
}
@@ -323,7 +323,7 @@ exports[`misc other complex template 1`] = `
const b27 = comp2({bundles: ctx['bundles'].dev,search: ctx['search']}, key + \`__3\`, node, this, null);
b25 = block25([], [b26, b27]);
}
return block1([attr1, txt1, hdlr2, hdlr3, prop2, hdlr4, hdlr5, ref1, hdlr6, ref2], [b2, b4, b14, b17, b22, b23, b24, b25]);
return block1([attr1, txt1, hdlr2, hdlr3, attr8, hdlr4, hdlr5, ref1, hdlr6, ref2], [b2, b4, b14, b17, b22, b23, b24, b25]);
}
}"
`;
@@ -1,250 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`changing an attribute with t-att- 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div block-attribute-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = ctx['v'];
return block1([attr1]);
}
}"
`;
exports[`dynamic input value: falsy values 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-property-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new String((0) === 0 ? 0 : ((0) || \\"\\"));
return block1([prop1]);
}
}"
`;
exports[`dynamic input value: falsy values 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-property-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new String((false) === 0 ? 0 : ((false) || \\"\\"));
return block1([prop1]);
}
}"
`;
exports[`dynamic input value: falsy values 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-property-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new String((undefined) === 0 ? 0 : ((undefined) || \\"\\"));
return block1([prop1]);
}
}"
`;
exports[`dynamic input value: falsy values 4`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-property-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new String(('') === 0 ? 0 : (('') || \\"\\"));
return block1([prop1]);
}
}"
`;
exports[`input of type checkbox with t-att-indeterminate 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input type=\\"checkbox\\" block-property-0=\\"indeterminate\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new Boolean(ctx['v']);
return block1([prop1]);
}
}"
`;
exports[`input type= checkbox, with t-att-checked 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input type=\\"checkbox\\" block-property-0=\\"checked\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new Boolean(ctx['flag']);
return block1([prop1]);
}
}"
`;
exports[`input with t-att-value (patching with same value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-property-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new String((ctx['v']) === 0 ? 0 : ((ctx['v']) || \\"\\"));
return block1([prop1]);
}
}"
`;
exports[`input with t-att-value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-property-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new String((ctx['v']) === 0 ? 0 : ((ctx['v']) || \\"\\"));
return block1([prop1]);
}
}"
`;
exports[`input, type checkbox, with t-att-checked (patching with same value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input type=\\"checkbox\\" block-property-0=\\"checked\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new Boolean(ctx['v']);
return block1([prop1]);
}
}"
`;
exports[`readonly and readOnly are both interpreted as the readOnly property 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input readonly=\\"\\"/>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`readonly and readOnly are both interpreted as the readOnly property 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input readOnly=\\"\\"/>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`readonly and readOnly are both interpreted as the readOnly property 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-property-0=\\"readOnly\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new Boolean(ctx['val']);
return block1([prop1]);
}
}"
`;
exports[`readonly and readOnly are both interpreted as the readOnly property 4`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-property-0=\\"readOnly\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new Boolean(ctx['val']);
return block1([prop1]);
}
}"
`;
exports[`select with t-att-value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<select block-property-0=\\"value\\"><option value=\\"potato\\">Potato</option><option value=\\"tomato\\">Tomato</option><option value=\\"onion\\">Onion</option></select>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new String((ctx['value']) === 0 ? 0 : ((ctx['value']) || \\"\\"));
return block1([prop1]);
}
}"
`;
exports[`textarea with t-att-value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<textarea block-property-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new String((ctx['v']) === 0 ? 0 : ((ctx['v']) || \\"\\"));
return block1([prop1]);
}
}"
`;
exports[`updating property with falsy value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-property-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let prop1 = new String((ctx['v']) === 0 ? 0 : ((ctx['v']) || \\"\\"));
return block1([prop1]);
}
}"
`;
exports[`various boolean html attributes 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div><input type=\\"checkbox\\" checked=\\"checked\\"/><input checked=\\"checked\\"/><div checked=\\"checked\\"/><div selected=\\"selected\\"/><option selected=\\"selected\\" other=\\"1\\"/><input readonly=\\"readonly\\"/><button disabled=\\"disabled\\"/></div>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
@@ -4,14 +4,13 @@ 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 = singleRefSetter(refs, \`myspan\${v1}\`);
let ref1 = (el) => refs[\`myspan\${v1}\`] = el;
return block1([ref1]);
}
}"
@@ -21,14 +20,13 @@ 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 = singleRefSetter(refs, \`myspan\${v1}\`);
let ref1 = (el) => refs[\`myspan\${v1}\`] = el;
return block1([ref1]);
}
}"
@@ -38,13 +36,12 @@ 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 = singleRefSetter(refs, \`myspan\`);
const ref1 = (el) => refs[\`myspan\`] = el;
return block1([ref1]);
}
}"
@@ -69,13 +66,12 @@ 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 = singleRefSetter(refs, \`name\`);
const ref1 = (el) => refs[\`name\`] = el;
return block1([ref1]);
}
}"
@@ -85,14 +81,13 @@ 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 = singleRefSetter(refs, \`name\`);
const ref1 = (el) => refs[\`name\`] = el;
let b2;
if (ctx['condition']) {
b2 = block2([ref1]);
@@ -106,7 +101,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, singleRefSetter, withKey } = helpers;
let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div block-ref=\\"0\\"><block-text-1/></div>\`);
@@ -120,7 +115,7 @@ exports[`t-ref refs in a loop 1`] = `
const key1 = ctx['item'];
const tKey_1 = ctx['item'];
const v1 = ctx['item'];
let ref1 = singleRefSetter(refs, (v1));
let ref1 = (el) => refs[(v1)] = el;
let txt1 = ctx['item'];
c_block2[i1] = withKey(block3([ref1, txt1]), tKey_1 + key1);
}
@@ -134,15 +129,14 @@ 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 = singleRefSetter(refs, \`name\`);
const ref2 = singleRefSetter(refs, \`p\`);
const ref1 = (el) => refs[\`name\`] = el;
const ref2 = (el) => refs[\`p\`] = el;
let b2;
if (ctx['condition']) {
b2 = block2([ref1]);
+179
View File
@@ -315,6 +315,54 @@ describe("attributes", () => {
).toBe('<div class="a b d"></div>');
});
test("changing an attribute with t-att-", () => {
// render input with initial value
const template = `<div t-att-value="v"/>`;
const bnode1 = renderToBdom(template, { v: "zucchini" });
const fixture = makeTestFixture();
mount(bnode1, fixture);
expect(fixture.innerHTML).toBe('<div value="zucchini"></div>');
const bnode2 = renderToBdom(template, { v: "potato" });
patch(bnode1, bnode2);
expect(fixture.innerHTML).toBe('<div value="potato"></div>');
const bnode3 = renderToBdom(template, { v: "" });
patch(bnode1, bnode3);
// not sure about this. maybe we want to remove the attribute?
expect(fixture.innerHTML).toBe('<div value=""></div>');
});
test("updating property with falsy value", async () => {
// render input with initial value
const template = `<input t-att-value="v"></input>`;
const bnode1 = renderToBdom(template, { v: false });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.value).toBe("");
patch(bnode1, renderToBdom(template, { v: "owl" }));
expect(input.value).toBe("owl");
patch(bnode1, renderToBdom(template, { v: false }));
expect(input.value).toBe("");
patch(bnode1, renderToBdom(template, { v: "owl" }));
expect(input.value).toBe("owl");
patch(bnode1, renderToBdom(template, { v: undefined }));
expect(input.value).toBe("");
patch(bnode1, renderToBdom(template, { v: "owl" }));
expect(input.value).toBe("owl");
patch(bnode1, renderToBdom(template, { v: null }));
expect(input.value).toBe("");
});
test("changing a class with t-att-class", () => {
// render input with initial value
const template = `<div t-att-class="v"/>`;
@@ -372,3 +420,134 @@ describe("attributes", () => {
expect(fixture.innerHTML).toBe('<div class="hoy a b"></div>');
});
});
describe("special cases for some specific html attributes/properties", () => {
test("input type= checkbox, with t-att-checked", () => {
const template = `<input type="checkbox" t-att-checked="flag"/>`;
const result = renderToString(template, { flag: true });
expect(result).toBe(`<input type="checkbox">`);
});
test("various boolean html attributes", () => {
// will cause the template to be snapshotted
renderToString(`
<div>
<input type="checkbox" checked="checked"/>
<input checked="checked"/>
<div checked="checked"/>
<div selected="selected"/>
<option selected="selected" other="1"/>
<input readonly="readonly"/>
<button disabled="disabled"/>
</div>
`);
});
test("input with t-att-value", () => {
// render input with initial value
const template = `<input t-att-value="v"/>`;
const bnode1 = renderToBdom(template, { v: "zucchini" });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.value).toBe("zucchini");
// change value manually in input, to simulate user input
input.value = "tomato";
expect(input.value).toBe("tomato");
// rerender with a different value, and patch actual dom, to check that
// input value was properly reset by owl
const bnode2 = renderToBdom(template, { v: "potato" });
patch(bnode1, bnode2);
expect(input.value).toBe("potato");
});
test("input with t-att-value (patching with same value", () => {
// render input with initial value
const template = `<input t-att-value="v"/>`;
const bnode1 = renderToBdom(template, { v: "zucchini" });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.value).toBe("zucchini");
// change value manually in input, to simulate user input
input.value = "tomato";
expect(input.value).toBe("tomato");
const bnode2 = renderToBdom(template, { v: "zucchini" });
patch(bnode1, bnode2);
expect(input.value).toBe("zucchini");
});
test("input, type checkbox, with t-att-checked (patching with same value", () => {
// render input with initial value
const template = `<input type="checkbox" t-att-checked="v"/>`;
const bnode1 = renderToBdom(template, { v: true });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.checked).toBe(true);
// change checked manually in input, to simulate user input
input.checked = false;
expect(input.checked).toBe(false);
const bnode2 = renderToBdom(template, { v: true });
patch(bnode1, bnode2);
expect(input.checked).toBe(true);
});
test("input of type checkbox with t-att-indeterminate", () => {
const template = `<input type="checkbox" t-att-indeterminate="v"/>`;
const bnode1 = renderToBdom(template, { v: true });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.indeterminate).toBe(true);
});
test("textarea with t-att-value", () => {
// render textarea with initial value
const template = `<textarea t-att-value="v"/>`;
const bnode1 = renderToBdom(template, { v: "zucchini" });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const elm = fixture.querySelector("textarea")!;
expect(elm.value).toBe("zucchini");
// change value manually in textarea, to simulate user textarea
elm.value = "tomato";
expect(elm.value).toBe("tomato");
// rerender with a different value, and patch actual dom, to check that
// textarea value was properly reset by owl
const bnode2 = renderToBdom(template, { v: "potato" });
patch(bnode1, bnode2);
expect(elm.value).toBe("potato");
});
test("select with t-att-value", () => {
const template = `
<select t-att-value="value">
<option value="potato">Potato</option>
<option value="tomato">Tomato</option>
<option value="onion">Onion</option>
</select>`;
const bnode1 = renderToBdom(template, { value: "tomato" });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const elm = fixture.querySelector("select")!;
expect(elm.value).toBe("tomato");
elm.value = "potato";
expect(elm.value).toBe("potato");
// rerender with a different value, and patch actual dom, to check that
// select value was properly reset by owl
const bnode2 = renderToBdom(template, { value: "onion" });
patch(bnode1, bnode2);
expect(elm.value).toBe("onion");
});
});
-3
View File
@@ -284,9 +284,6 @@ describe("t-on", () => {
expect(this).toBe(owner);
expect(val).toBe(444);
},
get this() {
return owner;
},
value: 444,
};
-213
View File
@@ -1,213 +0,0 @@
import { mount, patch } from "../../src/runtime/blockdom";
import { makeTestFixture, renderToBdom, renderToString, snapshotEverything } from "../helpers";
snapshotEverything();
test("changing an attribute with t-att-", () => {
// render input with initial value
const template = `<div t-att-value="v"/>`;
const bnode1 = renderToBdom(template, { v: "zucchini" });
const fixture = makeTestFixture();
mount(bnode1, fixture);
expect(fixture.innerHTML).toBe('<div value="zucchini"></div>');
const bnode2 = renderToBdom(template, { v: "potato" });
patch(bnode1, bnode2);
expect(fixture.innerHTML).toBe('<div value="potato"></div>');
const bnode3 = renderToBdom(template, { v: "" });
patch(bnode1, bnode3);
// not sure about this. maybe we want to remove the attribute?
expect(fixture.innerHTML).toBe('<div value=""></div>');
});
test("dynamic input value: falsy values", () => {
// 0 doesn't fall back to empty string
expect(renderToBdom(`<input t-att-value="0"/>`)).toEqual({ data: [new String("0")] });
expect(renderToBdom(`<input t-att-value="false"/>`)).toEqual({ data: [new String("")] });
expect(renderToBdom(`<input t-att-value="undefined"/>`)).toEqual({ data: [new String("")] });
expect(renderToBdom(`<input t-att-value="''"/>`)).toEqual({ data: [new String("")] });
});
test("updating property with falsy value", async () => {
// render input with initial value
const template = `<input t-att-value="v"></input>`;
const bnode1 = renderToBdom(template, { v: false });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.value).toBe("");
patch(bnode1, renderToBdom(template, { v: "owl" }));
expect(input.value).toBe("owl");
patch(bnode1, renderToBdom(template, { v: false }));
expect(input.value).toBe("");
patch(bnode1, renderToBdom(template, { v: "owl" }));
expect(input.value).toBe("owl");
patch(bnode1, renderToBdom(template, { v: undefined }));
expect(input.value).toBe("");
patch(bnode1, renderToBdom(template, { v: "owl" }));
expect(input.value).toBe("owl");
patch(bnode1, renderToBdom(template, { v: null }));
expect(input.value).toBe("");
});
test("input type= checkbox, with t-att-checked", () => {
const template = `<input type="checkbox" t-att-checked="flag"/>`;
const result = renderToString(template, { flag: true });
expect(result).toBe(`<input type="checkbox">`);
});
test("various boolean html attributes", () => {
// will cause the template to be snapshotted
renderToString(`
<div>
<input type="checkbox" checked="checked"/>
<input checked="checked"/>
<div checked="checked"/>
<div selected="selected"/>
<option selected="selected" other="1"/>
<input readonly="readonly"/>
<button disabled="disabled"/>
</div>
`);
});
test("input with t-att-value", () => {
// render input with initial value
const template = `<input t-att-value="v"/>`;
const bnode1 = renderToBdom(template, { v: "zucchini" });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.value).toBe("zucchini");
// change value manually in input, to simulate user input
input.value = "tomato";
expect(input.value).toBe("tomato");
// rerender with a different value, and patch actual dom, to check that
// input value was properly reset by owl
const bnode2 = renderToBdom(template, { v: "potato" });
patch(bnode1, bnode2);
expect(input.value).toBe("potato");
});
test("input with t-att-value (patching with same value", () => {
// render input with initial value
const template = `<input t-att-value="v"/>`;
const bnode1 = renderToBdom(template, { v: "zucchini" });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.value).toBe("zucchini");
// change value manually in input, to simulate user input
input.value = "tomato";
expect(input.value).toBe("tomato");
const bnode2 = renderToBdom(template, { v: "zucchini" });
patch(bnode1, bnode2);
expect(input.value).toBe("zucchini");
});
test("input, type checkbox, with t-att-checked (patching with same value", () => {
// render input with initial value
const template = `<input type="checkbox" t-att-checked="v"/>`;
const bnode1 = renderToBdom(template, { v: true });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.checked).toBe(true);
// change checked manually in input, to simulate user input
input.checked = false;
expect(input.checked).toBe(false);
const bnode2 = renderToBdom(template, { v: true });
patch(bnode1, bnode2);
expect(input.checked).toBe(true);
});
test("input of type checkbox with t-att-indeterminate", () => {
const template = `<input type="checkbox" t-att-indeterminate="v"/>`;
const bnode1 = renderToBdom(template, { v: true });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.indeterminate).toBe(true);
});
test("textarea with t-att-value", () => {
// render textarea with initial value
const template = `<textarea t-att-value="v"/>`;
const bnode1 = renderToBdom(template, { v: "zucchini" });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const elm = fixture.querySelector("textarea")!;
expect(elm.value).toBe("zucchini");
// change value manually in textarea, to simulate user textarea
elm.value = "tomato";
expect(elm.value).toBe("tomato");
// rerender with a different value, and patch actual dom, to check that
// textarea value was properly reset by owl
const bnode2 = renderToBdom(template, { v: "potato" });
patch(bnode1, bnode2);
expect(elm.value).toBe("potato");
});
test("select with t-att-value", () => {
const template = `
<select t-att-value="value">
<option value="potato">Potato</option>
<option value="tomato">Tomato</option>
<option value="onion">Onion</option>
</select>`;
const bnode1 = renderToBdom(template, { value: "tomato" });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const elm = fixture.querySelector("select")!;
expect(elm.value).toBe("tomato");
elm.value = "potato";
expect(elm.value).toBe("potato");
// rerender with a different value, and patch actual dom, to check that
// select value was properly reset by owl
const bnode2 = renderToBdom(template, { value: "onion" });
patch(bnode1, bnode2);
expect(elm.value).toBe("onion");
});
test("readonly and readOnly are both interpreted as the readOnly property", () => {
// render input with initial value
const staticTemplates = [`<input readonly=""/>`, `<input readOnly=""/>`];
for (let template of staticTemplates) {
const fixture = makeTestFixture();
const bnode1 = renderToBdom(template);
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.readOnly).toBe(true);
}
const dynamicTemplates = [`<input t-att-readonly="val"/>`, `<input t-att-readOnly="val"/>`];
for (let template of dynamicTemplates) {
const fixture = makeTestFixture();
const bnode1 = renderToBdom(template, { val: true });
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.readOnly).toBe(true);
const bnode2 = renderToBdom(template, { val: false });
patch(bnode1, bnode2);
expect(input.readOnly).toBe(false);
}
});
@@ -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']}, (Comp1).name + key + \`__1\`, node, this, Comp1));
return toggler(Comp1, comp1({displayGrandChild: ctx['displayGrandChild']}, key + \`__1\`, node, this, Comp1));
}
}"
`;
@@ -1213,45 +1213,6 @@ 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
) {
@@ -1815,7 +1776,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]}, (Comp1).name + key + \`__1__\${key1}\`, node, this, Comp1));
b3 = toggler(Comp1, comp1({key: ctx['arr'][0]}, key + \`__1__\${key1}\`, node, this, Comp1));
}
c_block1[i1] = withKey(multi([b3]), key1);
}
@@ -1849,7 +1810,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']}, (Comp1).name + tKey_1 + key + \`__1\`, node, this, Comp1)));
const b2 = toggler(tKey_1, toggler(Comp1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, this, Comp1)));
return toggler(tKey_1, block1([], [b2]));
}
}"
@@ -1875,7 +1836,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']}, (Comp1).name + tKey_1 + key + \`__1\`, node, this, Comp1)));
return toggler(tKey_1, toggler(Comp1, comp1({key: ctx['key']}, 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({}, (Comp1).name + key + \`__1\`, node, this, Comp1));
return toggler(Comp1, comp1({}, key + \`__1\`, node, this, Comp1));
}
return function template(ctx, node, key = \\"\\") {
@@ -940,10 +940,9 @@ exports[`can catch errors catching error, rethrow, render parent -- a main comp
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`cp\`] = v_block1[i1];
const key1 = ctx['cp'].id;
const v1 = ctx['this'];
const v2 = ctx['cp'];
const v1 = ctx['cp'];
const ctx1 = capture(ctx);
c_block1[i1] = withKey(comp2({onError: ()=>v1.cleanUp(v2.id),slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, this, null), key1);
c_block1[i1] = withKey(comp2({onError: ()=>this.cleanUp(v1.id),slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, this, null), key1);
}
return list(c_block1);
}
@@ -1010,19 +1009,18 @@ 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]}, (Comp1).name + key + \`__1\`, node, this, Comp1));
return toggler(Comp1, comp1({id: ctx['elem'][0]}, key + \`__1\`, node, this, Comp1));
}
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k_block1, v_block1, l_block1, c_block1] = prepareList(Object.entries(ctx['this'].elements));;
const [k_block1, v_block1, l_block1, c_block1] = prepareList(Object.entries(this.elements));;
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`elem\`] = v_block1[i1];
const key1 = ctx['elem'][0];
const v1 = ctx['this'];
const v2 = ctx['elem'];
const v1 = ctx['elem'];
const ctx1 = capture(ctx);
c_block1[i1] = withKey(comp2({onError: (_error)=>v1.onError(v2[0],_error),slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, this, null), key1);
c_block1[i1] = withKey(comp2({onError: (_error)=>this.onError(v1[0],_error),slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, this, null), key1);
}
return list(c_block1);
}
@@ -1157,7 +1155,7 @@ exports[`can catch errors onError in class inheritance is called if rethrown 2`]
return function template(ctx, node, key = \\"\\") {
let b2,b3;
if (!ctx['state'].error) {
b2 = text(ctx['this'].will.crash);
b2 = text(this.will.crash);
} else {
b3 = text(ctx['state'].error);
}
@@ -1188,7 +1186,7 @@ exports[`can catch errors onError in class inheritance is not called if no rethr
return function template(ctx, node, key = \\"\\") {
let b2,b3;
if (!ctx['state'].error) {
b2 = text(ctx['this'].will.crash);
b2 = text(this.will.crash);
} else {
b3 = text(ctx['state'].error);
}
@@ -1220,7 +1218,7 @@ exports[`errors and promises a rendering error in a sub component will reject th
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['this'].will.crash;
let txt1 = this.will.crash;
return block1([txt1]);
}
}"
@@ -1234,7 +1232,7 @@ exports[`errors and promises a rendering error will reject the mount promise 1`]
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['this'].will.crash;
let txt1 = this.will.crash;
return block1([txt1]);
}
}"
@@ -1279,7 +1277,7 @@ exports[`errors and promises a rendering error will reject the render promise 1`
return function template(ctx, node, key = \\"\\") {
let b2;
if (ctx['flag']) {
b2 = text(ctx['this'].will.crash);
b2 = text(this.will.crash);
}
return block1([], [b2]);
}
@@ -4,15 +4,14 @@ 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 = singleRefSetter(refs, \`input1\`);
const ref2 = singleRefSetter(refs, \`input2\`);
const ref1 = (el) => refs[\`input1\`] = el;
const ref2 = (el) => refs[\`input2\`] = el;
let b2;
if (ctx['state'].flag) {
b2 = block2([ref2]);
@@ -26,14 +25,13 @@ 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 = singleRefSetter(refs, \`input1\`);
const ref2 = singleRefSetter(refs, \`input2\`);
const ref1 = (el) => refs[\`input1\`] = el;
const ref2 = (el) => refs[\`input2\`] = el;
return block1([ref1, ref2]);
}
}"
@@ -266,13 +264,12 @@ 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 = singleRefSetter(refs, \`div\`);
const ref1 = (el) => refs[\`div\`] = el;
let b2;
if (ctx['state'].value) {
b2 = block2([ref1]);
@@ -356,13 +353,12 @@ 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 = singleRefSetter(refs, \`button\`);
const ref1 = (el) => refs[\`button\`] = el;
let txt1 = ctx['value'];
return block1([ref1, txt1]);
}
@@ -841,33 +841,6 @@ 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,39 +140,3 @@ 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,13 +4,12 @@ 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 = singleRefSetter(refs, \`div\`);
const ref1 = (el) => refs[\`div\`] = el;
return block1([ref1]);
}
}"
@@ -20,7 +19,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 { singleRefSetter, multiRefSetter } = helpers;
let { multiRefSetter } = helpers;
let block2 = createBlock(\`<div block-ref=\\"0\\"/>\`);
let block3 = createBlock(\`<span block-ref=\\"0\\"/>\`);
@@ -43,14 +42,13 @@ 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 = singleRefSetter(refs, \`root\`);
const ref1 = (el) => refs[\`root\`] = el;
let b2;
let txt1 = ctx['props'].tree.value;
if (ctx['props'].tree.child) {
@@ -61,33 +59,11 @@ 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, singleRefSetter, markRaw } = helpers;
let { capture, 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>\`);
@@ -95,7 +71,7 @@ exports[`refs refs are properly bound in slots 1`] = `
function slot1(ctx, node, key = \\"\\") {
const refs = this.__owl__.refs;
const ref1 = singleRefSetter(refs, \`myButton\`);
const ref1 = (el) => refs[\`myButton\`] = el;
let hdlr1 = [ctx['doSomething'], ctx];
return block2([hdlr1, ref1]);
}
@@ -128,7 +104,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 { singleRefSetter, multiRefSetter } = helpers;
let { 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 { singleRefSetter, markRaw } = helpers;
let { 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 = singleRefSetter(refs, \`div\`);
const ref1 = (el) => refs[\`div\`] = el;
const b2 = block2([ref1]);
const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]);
@@ -349,6 +349,42 @@ exports[`slots content is the default slot 2`] = `
}"
`;
exports[`slots default content is available as 0 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { zero, markRaw } = helpers;
const comp1 = app.createComponent(\`Dialog\`, true, true, false, true);
function slot1(ctx, node, key = \\"\\") {
const b2 = text(\`Before - \`);
const b3 = ctx[zero];
const b4 = text(\` - After\`);
return multi([b2, b3, b4]);
}
return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx}})}, key + \`__1\`, node, this, null);
}
}"
`;
exports[`slots default content is available as 0 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { callSlot } = helpers;
function defaultContent1(ctx, node, key = \\"\\") {
return text(\`default content\`);
}
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, {}, defaultContent1.bind(this));
}
}"
`;
exports[`slots default content is not rendered if named slot is provided 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -1992,8 +2028,7 @@ exports[`slots slot content is bound to caller (variation) 1`] = `
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"var\\", 1);
const v1 = ctx['this'];
let hdlr1 = [()=>v1.inc(), ctx];
let hdlr1 = [()=>this.inc(), ctx];
return block1([hdlr1]);
}
@@ -2360,8 +2395,7 @@ exports[`slots slots are properly bound to correct component 2`] = `
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"var\\", 1);
const v1 = ctx['this'];
let hdlr1 = [()=>v1.increment(), ctx];
let hdlr1 = [()=>this.increment(), ctx];
let txt1 = ctx['state'].value;
return block1([hdlr1, txt1]);
}
@@ -363,7 +363,7 @@ exports[`style and class handling error in subcomponent with class 2`] = `
return function template(ctx, node, key = \\"\\") {
let attr1 = ctx['props'].class;
let txt1 = ctx['this'].will.crash;
let txt1 = this.will.crash;
return block1([attr1, txt1]);
}
}"
@@ -109,8 +109,7 @@ exports[`t-call handlers are properly bound through a dynamic t-call 2`] = `
let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['this'];
let hdlr1 = [()=>v1.update(), ctx];
let hdlr1 = [()=>this.update(), ctx];
return block1([hdlr1]);
}
}"
@@ -169,9 +168,8 @@ exports[`t-call handlers with arguments are properly bound through a t-call 2`]
let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['this'];
const v2 = ctx['a'];
let hdlr1 = [()=>v1.update(v2), ctx];
const v1 = ctx['a'];
let hdlr1 = [()=>this.update(v1), ctx];
return block1([hdlr1]);
}
}"
@@ -289,7 +287,7 @@ exports[`t-call recursive t-call binding this -- static t-call 2`] = `
ctx[isBoundary] = 1
let b2;
if (ctx['level']<2) {
let hdlr1 = [\\"stop\\", ctx['onClicked'].bind(ctx['this']), ctx];
let hdlr1 = [\\"stop\\", ctx['onClicked'].bind(this), ctx];
let txt1 = ctx['level'];
const b3 = block3([hdlr1, txt1]);
ctx = Object.create(ctx);
@@ -534,32 +532,35 @@ 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 { singleRefSetter, bind, capture, isBoundary, withDefault, setContextValue, markRaw } = helpers;
let { 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>\`);
let block4 = createBlock(\`<div block-ref=\\"0\\">I'm the default slot</div>\`);
let block5 = createBlock(\`<div><block-text-0/></div>\`);
let block6 = createBlock(\`<div><block-text-0/></div>\`);
function slot1(ctx, node, key = \\"\\") {
const refs = this.__owl__.refs;
const ref2 = singleRefSetter(refs, \`myRef2\`);
const ref2 = (el) => refs[\`myRef2\`] = el;
ctx = Object.create(ctx);
ctx[isBoundary] = 1
const b4 = block4([ref2]);
setContextValue(ctx, \\"test\\", 3);
let txt1 = ctx['test'];
let txt1 = this.__owl__.name;
const b5 = block5([txt1]);
return multi([b4, b5]);
let txt2 = ctx['test'];
const b6 = block6([txt2]);
return multi([b4, b5, b6]);
}
return function template(ctx, node, key = \\"\\") {
const refs = this.__owl__.refs;
const ref1 = singleRefSetter(refs, \`myRef\`);
const ref1 = (el) => refs[\`myRef\`] = el;
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);
return multi([b2, b6]);
const b7 = comp1({prop: bind(this, ctx['method']),slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return multi([b2, b7]);
}
}"
`;
@@ -623,27 +624,3 @@ exports[`t-call t-call-context: slots don't make component available again when
}
}"
`;
exports[`t-call t-call-context: this is not available inside t-call-context 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const callTemplate_1 = app.getTemplate(\`someTemplate\`);
return function template(ctx, node, key = \\"\\") {
let ctx1 = {};
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
}
}"
`;
exports[`t-call t-call-context: this is not available inside t-call-context 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['this']);
}
}"
`;
@@ -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({}, (Comp1).name + key + \`__1\`, node, this, Comp1));
const b2 = toggler(Comp1, comp1({}, 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({}, (Comp1).name + tKey_1 + key + \`__1\`, node, this, Comp1)));
return toggler(tKey_1, toggler(Comp1, comp1({}, 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({}, (Comp1).name + tKey_1 + key + \`__1\`, node, this, Comp1)));
return toggler(tKey_1, toggler(Comp1, comp1({}, 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({}, (Comp1).name + key + \`__1\`, node, this, Comp1));
const b2 = toggler(Comp1, comp1({}, 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({}, (Comp1).name + key + \`__1\`, node, this, Comp1));
return toggler(Comp1, comp1({}, 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({}, (Comp1).name + key + \`__1\`, node, this, Comp1));
return toggler(Comp1, comp1({}, key + \`__1\`, node, this, Comp1));
}
}"
`;
@@ -6,15 +6,15 @@ exports[`t-model directive .lazy modifier 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-property-0=\\"value\\" block-handler-1=\\"change\\"/><span><block-text-2/></span></div>\`);
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"change\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'text';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let txt1 = ctx['state'].text;
return block1([prop1, hdlr1, txt1]);
return block1([attr1, hdlr1, txt1]);
}
}"
`;
@@ -25,15 +25,15 @@ exports[`t-model directive .number modifier 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-property-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'number';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = toNumber(ev.target.value); }];
let txt1 = ctx['state'].number;
return block1([prop1, hdlr1, txt1]);
return block1([attr1, hdlr1, txt1]);
}
}"
`;
@@ -44,15 +44,15 @@ exports[`t-model directive .trim modifier 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-property-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'text';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value.trim(); }];
let txt1 = ctx['state'].text;
return block1([prop1, hdlr1, txt1]);
return block1([attr1, hdlr1, txt1]);
}
}"
`;
@@ -63,15 +63,15 @@ exports[`t-model directive basic use, on an input 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-property-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'text';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let txt1 = ctx['state'].text;
return block1([prop1, hdlr1, txt1]);
return block1([attr1, hdlr1, txt1]);
}
}"
`;
@@ -82,15 +82,15 @@ exports[`t-model directive basic use, on an input with bracket expression 1`] =
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-property-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'text';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let txt1 = ctx['state'].text;
return block1([prop1, hdlr1, txt1]);
return block1([attr1, hdlr1, txt1]);
}
}"
`;
@@ -101,15 +101,15 @@ exports[`t-model directive basic use, on another key in component 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-property-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['some'];
const expr1 = 'text';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let txt1 = ctx['some'].text;
return block1([prop1, hdlr1, txt1]);
return block1([attr1, hdlr1, txt1]);
}
}"
`;
@@ -120,15 +120,15 @@ exports[`t-model directive can also define t-on directive on same event, part 1
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-property-0=\\"value\\" block-handler-1=\\"input\\" block-handler-2=\\"input\\"/></div>\`);
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\" block-handler-2=\\"input\\"/></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'text';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let hdlr2 = [ctx['onInput'], ctx];
return block1([prop1, hdlr1, hdlr2]);
return block1([attr1, hdlr1, hdlr2]);
}
}"
`;
@@ -139,25 +139,25 @@ exports[`t-model directive can also define t-on directive on same event, part 2
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input type=\\"radio\\" id=\\"one\\" value=\\"One\\" block-property-0=\\"checked\\" block-handler-1=\\"click\\" block-handler-2=\\"click\\"/><input type=\\"radio\\" id=\\"two\\" value=\\"Two\\" block-property-3=\\"checked\\" block-handler-4=\\"click\\" block-handler-5=\\"click\\"/><input type=\\"radio\\" id=\\"three\\" value=\\"Three\\" block-property-6=\\"checked\\" block-handler-7=\\"click\\" block-handler-8=\\"click\\"/></div>\`);
let block1 = createBlock(\`<div><input type=\\"radio\\" id=\\"one\\" value=\\"One\\" block-attribute-0=\\"checked\\" block-handler-1=\\"click\\" block-handler-2=\\"click\\"/><input type=\\"radio\\" id=\\"two\\" value=\\"Two\\" block-attribute-3=\\"checked\\" block-handler-4=\\"click\\" block-handler-5=\\"click\\"/><input type=\\"radio\\" id=\\"three\\" value=\\"Three\\" block-attribute-6=\\"checked\\" block-handler-7=\\"click\\" block-handler-8=\\"click\\"/></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'choice';
let prop1 = bExpr1[expr1] === 'One';
let attr1 = bExpr1[expr1] === 'One';
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let hdlr2 = [ctx['onClick'], ctx];
const bExpr2 = ctx['state'];
const expr2 = 'choice';
let prop2 = bExpr2[expr2] === 'Two';
let attr2 = bExpr2[expr2] === 'Two';
let hdlr3 = [(ev) => { bExpr2[expr2] = ev.target.value; }];
let hdlr4 = [ctx['onClick'], ctx];
const bExpr3 = ctx['state'];
const expr3 = 'choice';
let prop3 = bExpr3[expr3] === 'Three';
let attr3 = bExpr3[expr3] === 'Three';
let hdlr5 = [(ev) => { bExpr3[expr3] = ev.target.value; }];
let hdlr6 = [ctx['onClick'], ctx];
return block1([prop1, hdlr1, hdlr2, prop2, hdlr3, hdlr4, prop3, hdlr5, hdlr6]);
return block1([attr1, hdlr1, hdlr2, attr2, hdlr3, hdlr4, attr3, hdlr5, hdlr6]);
}
}"
`;
@@ -168,7 +168,7 @@ exports[`t-model directive following a scope protecting directive (e.g. t-set) 1
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { isBoundary, withDefault, setContextValue, toNumber } = helpers;
let block1 = createBlock(\`<div><input block-property-0=\\"value\\" block-handler-1=\\"input\\"/></div>\`);
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/></div>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
@@ -176,9 +176,9 @@ exports[`t-model directive following a scope protecting directive (e.g. t-set) 1
setContextValue(ctx, \\"admiral\\", 'Bruno');
const bExpr1 = ctx['state'];
const expr1 = 'text';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
return block1([prop1, hdlr1]);
return block1([attr1, hdlr1]);
}
}"
`;
@@ -190,7 +190,7 @@ exports[`t-model directive in a t-foreach 1`] = `
let { prepareList, toNumber, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<input type=\\"checkbox\\" block-property-0=\\"checked\\" block-handler-1=\\"input\\"/>\`);
let block3 = createBlock(\`<input type=\\"checkbox\\" block-attribute-0=\\"checked\\" block-handler-1=\\"input\\"/>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
@@ -200,9 +200,9 @@ exports[`t-model directive in a t-foreach 1`] = `
const key1 = ctx['thing'].id;
const bExpr1 = ctx['thing'];
const expr1 = 'f';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.checked; }];
c_block2[i1] = withKey(block3([prop1, hdlr1]), key1);
c_block2[i1] = withKey(block3([attr1, hdlr1]), key1);
}
const b2 = list(c_block2);
return block1([], [b2]);
@@ -217,7 +217,7 @@ exports[`t-model directive in a t-foreach, part 2 1`] = `
let { prepareList, toNumber, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<input block-property-0=\\"value\\" block-handler-1=\\"input\\"/>\`);
let block3 = createBlock(\`<input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
@@ -228,9 +228,9 @@ exports[`t-model directive in a t-foreach, part 2 1`] = `
const key1 = ctx['thing_index'];
const bExpr1 = ctx['state'];
const expr1 = ctx['thing_index'];
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
c_block2[i1] = withKey(block3([prop1, hdlr1]), key1);
c_block2[i1] = withKey(block3([attr1, hdlr1]), key1);
}
const b2 = list(c_block2);
return block1([], [b2]);
@@ -245,7 +245,7 @@ exports[`t-model directive in a t-foreach, part 3 1`] = `
let { prepareList, toNumber, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<input block-property-0=\\"value\\" block-handler-1=\\"input\\"/>\`);
let block3 = createBlock(\`<input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
@@ -256,9 +256,9 @@ exports[`t-model directive in a t-foreach, part 3 1`] = `
const key1 = ctx['name_index'];
const bExpr1 = ctx['state'].values;
const expr1 = ctx['name'];
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
c_block2[i1] = withKey(block3([prop1, hdlr1]), key1);
c_block2[i1] = withKey(block3([attr1, hdlr1]), key1);
}
const b2 = list(c_block2);
return block1([], [b2]);
@@ -272,15 +272,15 @@ exports[`t-model directive on a select 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><select block-property-0=\\"value\\" block-handler-1=\\"change\\"><option value=\\"\\">Please select one</option><option value=\\"red\\">Red</option><option value=\\"blue\\">Blue</option></select><span>Choice: <block-text-2/></span></div>\`);
let block1 = createBlock(\`<div><select block-attribute-0=\\"value\\" block-handler-1=\\"change\\"><option value=\\"\\">Please select one</option><option value=\\"red\\">Red</option><option value=\\"blue\\">Blue</option></select><span>Choice: <block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'color';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let txt1 = ctx['state'].color;
return block1([prop1, hdlr1, txt1]);
return block1([attr1, hdlr1, txt1]);
}
}"
`;
@@ -291,14 +291,14 @@ exports[`t-model directive on a select, initial state 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><select block-property-0=\\"value\\" block-handler-1=\\"change\\"><option value=\\"\\">Please select one</option><option value=\\"red\\">Red</option><option value=\\"blue\\">Blue</option></select></div>\`);
let block1 = createBlock(\`<div><select block-attribute-0=\\"value\\" block-handler-1=\\"change\\"><option value=\\"\\">Please select one</option><option value=\\"red\\">Red</option><option value=\\"blue\\">Blue</option></select></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'color';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
return block1([prop1, hdlr1]);
return block1([attr1, hdlr1]);
}
}"
`;
@@ -309,15 +309,15 @@ exports[`t-model directive on a sub state key 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-property-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'].something;
const expr1 = 'text';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let txt1 = ctx['state'].something.text;
return block1([prop1, hdlr1, txt1]);
return block1([attr1, hdlr1, txt1]);
}
}"
`;
@@ -328,19 +328,19 @@ exports[`t-model directive on an input type=radio 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input type=\\"radio\\" id=\\"one\\" value=\\"One\\" block-property-0=\\"checked\\" block-handler-1=\\"click\\"/><input type=\\"radio\\" id=\\"two\\" value=\\"Two\\" block-property-2=\\"checked\\" block-handler-3=\\"click\\"/><span>Choice: <block-text-4/></span></div>\`);
let block1 = createBlock(\`<div><input type=\\"radio\\" id=\\"one\\" value=\\"One\\" block-attribute-0=\\"checked\\" block-handler-1=\\"click\\"/><input type=\\"radio\\" id=\\"two\\" value=\\"Two\\" block-attribute-2=\\"checked\\" block-handler-3=\\"click\\"/><span>Choice: <block-text-4/></span></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'choice';
let prop1 = bExpr1[expr1] === 'One';
let attr1 = bExpr1[expr1] === 'One';
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
const bExpr2 = ctx['state'];
const expr2 = 'choice';
let prop2 = bExpr2[expr2] === 'Two';
let attr2 = bExpr2[expr2] === 'Two';
let hdlr2 = [(ev) => { bExpr2[expr2] = ev.target.value; }];
let txt1 = ctx['state'].choice;
return block1([prop1, hdlr1, prop2, hdlr2, txt1]);
return block1([attr1, hdlr1, attr2, hdlr2, txt1]);
}
}"
`;
@@ -351,18 +351,18 @@ exports[`t-model directive on an input type=radio, with initial value 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input type=\\"radio\\" id=\\"one\\" value=\\"One\\" block-property-0=\\"checked\\" block-handler-1=\\"click\\"/><input type=\\"radio\\" id=\\"two\\" value=\\"Two\\" block-property-2=\\"checked\\" block-handler-3=\\"click\\"/></div>\`);
let block1 = createBlock(\`<div><input type=\\"radio\\" id=\\"one\\" value=\\"One\\" block-attribute-0=\\"checked\\" block-handler-1=\\"click\\"/><input type=\\"radio\\" id=\\"two\\" value=\\"Two\\" block-attribute-2=\\"checked\\" block-handler-3=\\"click\\"/></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'choice';
let prop1 = bExpr1[expr1] === 'One';
let attr1 = bExpr1[expr1] === 'One';
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
const bExpr2 = ctx['state'];
const expr2 = 'choice';
let prop2 = bExpr2[expr2] === 'Two';
let attr2 = bExpr2[expr2] === 'Two';
let hdlr2 = [(ev) => { bExpr2[expr2] = ev.target.value; }];
return block1([prop1, hdlr1, prop2, hdlr2]);
return block1([attr1, hdlr1, attr2, hdlr2]);
}
}"
`;
@@ -373,20 +373,20 @@ exports[`t-model directive on an input, type=checkbox 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input type=\\"checkbox\\" block-property-0=\\"checked\\" block-handler-1=\\"input\\"/><span><block-child-0/><block-child-1/></span></div>\`);
let block1 = createBlock(\`<div><input type=\\"checkbox\\" block-attribute-0=\\"checked\\" block-handler-1=\\"input\\"/><span><block-child-0/><block-child-1/></span></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2,b3;
const bExpr1 = ctx['state'];
const expr1 = 'flag';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.checked; }];
if (ctx['state'].flag) {
b2 = text(\`yes\`);
} else {
b3 = text(\`no\`);
}
return block1([prop1, hdlr1], [b2, b3]);
return block1([attr1, hdlr1], [b2, b3]);
}
}"
`;
@@ -397,15 +397,15 @@ exports[`t-model directive on an textarea 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><textarea block-property-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
let block1 = createBlock(\`<div><textarea block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'text';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let txt1 = ctx['state'].text;
return block1([prop1, hdlr1, txt1]);
return block1([attr1, hdlr1, txt1]);
}
}"
`;
@@ -416,15 +416,15 @@ exports[`t-model directive t-model is applied before t-on-input 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-property-0=\\"value\\" block-handler-1=\\"input\\" block-handler-2=\\"input\\"/></div>\`);
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\" block-handler-2=\\"input\\"/></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'text';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let hdlr2 = [ctx['onInput'], ctx];
return block1([prop1, hdlr1, hdlr2]);
return block1([attr1, hdlr1, hdlr2]);
}
}"
`;
@@ -435,14 +435,14 @@ exports[`t-model directive t-model on an input with an undefined value 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<input block-property-0=\\"value\\" block-handler-1=\\"input\\"/>\`);
let block1 = createBlock(\`<input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'text';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
return block1([prop1, hdlr1]);
return block1([attr1, hdlr1]);
}
}"
`;
@@ -453,17 +453,17 @@ exports[`t-model directive t-model on select with static options 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><select block-property-0=\\"value\\" block-handler-1=\\"change\\"><option value=\\"a\\"><block-text-2/></option><option value=\\"b\\"><block-text-3/></option><option value=\\"c\\"><block-text-4/></option></select></div>\`);
let block1 = createBlock(\`<div><select block-attribute-0=\\"value\\" block-handler-1=\\"change\\"><option value=\\"a\\"><block-text-2/></option><option value=\\"b\\"><block-text-3/></option><option value=\\"c\\"><block-text-4/></option></select></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'];
const expr1 = 'model';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let txt1 = 'a';
let txt2 = 'b';
let txt3 = 'c';
return block1([prop1, hdlr1, txt1, txt2, txt3]);
return block1([attr1, hdlr1, txt1, txt2, txt3]);
}
}"
`;
@@ -569,36 +569,6 @@ exports[`t-model directive t-model with dynamic values on select options in fore
}"
`;
exports[`t-model directive t-model with radio button group in t-foreach 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { prepareList, toNumber, withKey } = helpers;
let block1 = createBlock(\`<div id=\\"get_data\\" block-handler-0=\\"click\\"><block-child-0/></div>\`);
let block3 = createBlock(\`<input type=\\"radio\\" name=\\"radio_group\\" block-property-0=\\"value\\" block-attribute-1=\\"id\\" block-property-2=\\"checked\\" block-handler-3=\\"click\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['getData'], ctx];
ctx = Object.create(ctx);
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['options']);;
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`opt\`] = v_block2[i1];
const key1 = ctx['opt'];
let prop1 = new String((ctx['opt']) === 0 ? 0 : ((ctx['opt']) || \\"\\"));
let attr1 = ctx['opt'];
const bExpr1 = ctx['state'];
const expr1 = 'group';
let prop2 = bExpr1[expr1] === ctx['opt'];
let hdlr2 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
c_block2[i1] = withKey(block3([prop1, attr1, prop2, hdlr2]), key1);
}
const b2 = list(c_block2);
return block1([hdlr1], [b2]);
}
}"
`;
exports[`t-model directive two inputs in a div alternating with a t-if 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -606,24 +576,24 @@ exports[`t-model directive two inputs in a div alternating with a t-if 1`] = `
let { toNumber } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
let block2 = createBlock(\`<input class=\\"a\\" block-property-0=\\"value\\" block-handler-1=\\"input\\"/>\`);
let block3 = createBlock(\`<input class=\\"b\\" block-property-0=\\"value\\" block-handler-1=\\"input\\"/>\`);
let block2 = createBlock(\`<input class=\\"a\\" block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/>\`);
let block3 = createBlock(\`<input class=\\"b\\" block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let b2,b3;
if (ctx['state'].flag) {
const bExpr1 = ctx['state'];
const expr1 = 'text1';
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
b2 = block2([prop1, hdlr1]);
b2 = block2([attr1, hdlr1]);
}
if (!ctx['state'].flag) {
const bExpr2 = ctx['state'];
const expr2 = 'text2';
let prop2 = bExpr2[expr2];
let attr2 = bExpr2[expr2];
let hdlr2 = [(ev) => { bExpr2[expr2] = ev.target.value; }];
b3 = block3([prop2, hdlr2]);
b3 = block3([attr2, hdlr2]);
}
return block1([], [b2, b3]);
}
@@ -636,15 +606,15 @@ exports[`t-model directive with expression having a changing key 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-property-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'].something;
const expr1 = ctx['text'].key;
let prop1 = bExpr1[expr1];
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let txt1 = ctx['state'].something[ctx['text'].key];
return block1([prop1, hdlr1, txt1]);
return block1([attr1, hdlr1, txt1]);
}
}"
`;
@@ -111,9 +111,8 @@ exports[`t-on t-on method call in t-foreach 1`] = `
const key1 = ctx['val'];
let txt1 = ctx['val_index'];
let txt2 = ctx['val']+'';
const v1 = ctx['this'];
const v2 = ctx['val'];
let hdlr1 = [()=>v1.addVal(v2), ctx];
const v1 = ctx['val'];
let hdlr1 = [()=>this.addVal(v1), ctx];
c_block2[i1] = withKey(block3([txt1, txt2, hdlr1]), key1);
}
const b2 = list(c_block2);
@@ -198,9 +197,8 @@ exports[`t-on t-on on components and t-foreach 1`] = `
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`name\`] = v_block1[i1];
const key1 = ctx['name'];
const v1 = ctx['this'];
const v2 = ctx['name'];
const hdlr1 = [()=>v1.log(v2), ctx];
const v1 = ctx['name'];
const hdlr1 = [()=>this.log(v1), ctx];
c_block1[i1] = withKey(catcher1(comp1({value: ctx['name']}, key + \`__1__\${key1}\`, node, this, null), [hdlr1]), key1);
}
return list(c_block1);
@@ -295,9 +293,8 @@ exports[`t-on t-on on components, with a handler update 1`] = `
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"name\\", ctx['state'].name);
const v1 = ctx['this'];
const v2 = ctx['name'];
const hdlr1 = [()=>v1.log(v2), ctx];
const v1 = ctx['name'];
const hdlr1 = [()=>this.log(v1), ctx];
return catcher1(comp1({value: ctx['name']}, key + \`__1\`, node, this, null), [hdlr1]);
}
}"
@@ -396,8 +393,7 @@ exports[`t-on t-on on t-set-slots 1`] = `
function slot1(ctx, node, key = \\"\\") {
const b6 = block6();
const b7 = block7();
const v1 = ctx['this'];
const hdlr1 = [()=>v1.state.count++, ctx];
const hdlr1 = [()=>this.state.count++, ctx];
return catcher1(multi([b6, b7]), [hdlr1]);
}
@@ -454,8 +450,7 @@ exports[`t-on t-on on t-slots 2`] = `
const b2 = text(\` [\`);
const b3 = text(ctx['state'].count);
const b4 = text(\`] \`);
const v1 = ctx['this'];
const hdlr1 = [()=>v1.state.count++, ctx];
const hdlr1 = [()=>this.state.count++, ctx];
const b5 = catcher1(callSlot(ctx, node, key, 'default', false, {}), [hdlr1]);
return multi([b2, b3, b4, b5]);
}
-59
View File
@@ -1,7 +1,6 @@
import {
App,
Component,
ComponentConstructor,
mount,
onMounted,
onRendered,
@@ -4068,64 +4067,6 @@ 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 -24
View File
@@ -1,5 +1,5 @@
import { makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
import { Component, onError, xml, mount, OwlError, useState } from "../../src";
import { Component, onError, xml, mount, OwlError } from "../../src";
import { App, DEV_MSG } from "../../src/runtime/app";
import { validateProps } from "../../src/runtime/template_helpers";
import { Schema } from "../../src/runtime/validation";
@@ -682,29 +682,6 @@ 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 {
-32
View File
@@ -7,7 +7,6 @@ import {
onWillUnmount,
useState,
xml,
toRaw,
} from "../../src";
import { makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers";
@@ -233,34 +232,3 @@ 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) }]);
});
});
+2 -39
View File
@@ -1,14 +1,6 @@
import {
App,
Component,
mount,
onMounted,
onPatched,
useRef,
useState,
xml,
} from "../../src/index";
import { App, Component, mount, onMounted, useRef, useState } from "../../src/index";
import { logStep, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
import { xml } from "../../src/index";
snapshotEverything();
let fixture: HTMLElement;
@@ -136,33 +128,4 @@ 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"));
});
});
+13
View File
@@ -1933,4 +1933,17 @@ describe("slots", () => {
"<p>1 hello <div>child</div></p><p>2 hello <div>child</div></p>"
);
});
test("default content is available as 0", async () => {
class Dialog extends Component {
static template = xml`<t t-slot="default">default content</t>`;
}
class Parent extends Component {
static template = xml`<Dialog>Before - <t t-out="0"/> - After</Dialog>`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("Before - default content - After");
});
});
+2 -17
View File
@@ -345,13 +345,14 @@ describe("t-call", () => {
<Child prop.bind="method">
<div t-ref="myRef2">I'm the default slot</div>
<t t-set="test" t-value="3"/>
<div t-esc="this.__owl__.name"/>
<div t-esc="test"/>
</Child>
</t>
</templates>`,
});
expect(fixture.innerHTML).toBe(
"<div>outside slot</div><div>I'm the default slot</div><div>3</div>"
"<div>outside slot</div><div>I'm the default slot</div><div>Root</div><div>3</div>"
);
expect(Object.keys(child.__owl__.refs)).toEqual([]);
expect(Object.keys(root.__owl__.refs)).toEqual(["myRef", "myRef2"]);
@@ -382,20 +383,4 @@ describe("t-call", () => {
});
expect(fixture.innerHTML).toBe("");
});
test("t-call-context: this is not available inside t-call-context", async () => {
class Root extends Component {
static template = xml`<t t-call="someTemplate" t-call-context="{}"/>`;
}
await mount(Root, fixture, {
templates: `
<templates>
<t t-name="someTemplate">
<t t-esc="this"/>
</t>
</templates>`,
});
expect(fixture.innerHTML).toBe("");
});
});
-31
View File
@@ -644,35 +644,4 @@ describe("t-model directive", () => {
const input = fixture.querySelector("input")!;
await editInput(input, "Beam me up, Scotty");
});
test("t-model with radio button group in t-foreach", async () => {
expect.assertions(6);
const steps: string[] = [];
class SomeComponent extends Component {
static template = xml`
<div t-on-click="getData" id="get_data">
<t t-foreach="options" t-as="opt" t-key="opt">
<input type="radio" name="radio_group" t-model="state.group" t-att-value="opt" t-att-id="opt"/>
</t>
</div>
`;
state = useState({ group: "scotty" });
options = ["beam", "scotty"];
getData() {
steps.push(`group: ${this.state.group}`);
}
}
await mount(SomeComponent, fixture);
const divEl = fixture.querySelector("#get_data") as HTMLElement;
expect(fixture.querySelector("input:checked")!.getAttribute("id")).toBe("scotty");
divEl.click();
expect(steps).toEqual(["group: scotty"]);
fixture.querySelector("input")!.click();
expect(steps).toEqual(["group: scotty", "group: beam"]);
await nextTick();
expect(fixture.querySelector("input:checked")!.getAttribute("id")).toBe("beam");
divEl.click();
expect(steps).toEqual(["group: scotty", "group: beam", "group: beam"]);
});
});
+1 -1
View File
@@ -646,7 +646,7 @@ exports[`Portal portal destroys on crash 2`] = `
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props'].error&&ctx['this'].will.crash;
let txt1 = ctx['props'].error&&this.will.crash;
return block1([txt1]);
}
}"
+1 -1
View File
@@ -48,7 +48,7 @@ function writeToFile(filepath, data) {
}
// adapted from https://medium.com/@mhagemann/the-ultimate-way-to-slugify-a-url-string-in-javascript-b8e4a0d849e1
const a = -_,:;";
const a = "·_,:;";
const p = new RegExp(a.split("").join("|"), "g");
function slugify(str) {
+6 -35
View File
@@ -47,18 +47,6 @@ async function startRelease() {
let file = await ask(`Release notes (${REL_NOTES_FILE}): `);
file = file || REL_NOTES_FILE;
let content;
if (!fs.existsSync(`./${file}`)) {
let lastRelease = await getOutput("git log --grep='\\[REL\\]' -n 1 --pretty=%H");
const commitsSinceLastRelease = await getOutput(`git log ${lastRelease.trim()}..HEAD --pretty=%s`);
const commitsAsMdList = commitsSinceLastRelease.trim().split("\n").map(l => " - " + l).join("\n");
log(`${file} did not exist, created a template containing all commits since last release.`)
fs.writeFileSync(file, `# v${next}\n\n${commitsAsMdList}`);
const shouldContinue = await ask(`Check that the contents of ${file} is correct, then press y to continue: `);
if (shouldContinue.toLowerCase() !== "y") {
log("aborted");
return;
}
}
try {
content = await readFile("./" + file);
} catch (e) {
@@ -116,7 +104,7 @@ async function startRelease() {
// ---------------------------------------------------------------------------
log(`Step 7/${STEPS}: Creating the release...`);
const relaseResult = await execCommand(`gh release create v${next} dist/*.js ${draft} -F ${file}`);
const relaseResult = await execCommand(`gh release create v${next} dist/*.js ${draft} -F ${REL_NOTES_FILE}`);
if (relaseResult !== 0) {
logError("github release failed. Aborting.");
return;
@@ -132,7 +120,7 @@ async function startRelease() {
if (shouldUploadPlayground) {
log(`Bonus step: publishing new release on playground...`);
let owl_code = null;
let status = 0
status = 0
try {
owl_code = await readFile("dist/owl.iife.js");
@@ -142,8 +130,7 @@ async function startRelease() {
return;
}
status |= await execCommand("git checkout gh-pages");
status |= await execCommand("git pull --rebase");
status += await execCommand("git checkout gh-pages");
if (status !== 0) {
logError("Couldn't switch to gh-pages branch")
@@ -157,9 +144,9 @@ async function startRelease() {
return;
}
status |= await execCommand(`git commit -am "[IMP] update owl to v${next}"`);
status |= await execCommand(`git push origin gh-pages`);
status |= await execCommand("git checkout -");
status += await execCommand(`git commit -am "[IMP] update owl to v${next}"`);
status += await execCommand(`git push origin gh-pages`);
status += await execCommand("git checkout -");
if (status !== 0) {
logError("Something went wrong for the playground update.")
}
@@ -244,19 +231,3 @@ async function replaceInFile(file, from, to) {
});
});
}
async function getOutput(command) {
return new Promise((resolve, reject) => {
const childProcess = exec(command, (err, stdout, stderr) => {
if (err) {
reject(err);
}
resolve(stdout);
});
childProcess.on("exit", code => {
if (code !== 0) {
reject(code);
}
});
});
}