[IMP] qweb: re-add support of t-on directive

We add some test for the t-on directive.

For making them pass, it was necessary to change the code produced by
compileTForeach: the const declaration is not done by using generateId
and there was some conflict with the variable names produced in
captureExpression. Consequently, many snapshots had to be changed.

Code prettification has been done too.
This commit is contained in:
Mathieu Duckerts-Antoine
2021-10-15 13:08:07 +02:00
committed by Aaron Bohy
parent ee1ef20ce1
commit d6668e3439
16 changed files with 628 additions and 326 deletions
@@ -463,15 +463,15 @@ exports[`basics list of two sub components inside other nodes 2`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(ctx['state'].blips);
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`blip\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].blips);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`blip\`] = v_block2[i1];
let key1 = ctx['blip'].id;
let b4 = component(\`SubWidget\`, {}, key + \`__1__\${key1}\`, node, ctx);
let b5 = component(\`SubWidget\`, {}, key + \`__2__\${key1}\`, node, ctx);
c2[i1] = withKey(block3([], [b4, b5]), key1);
c_block2[i1] = withKey(block3([], [b4, b5]), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -995,13 +995,13 @@ exports[`basics updating a component with t-foreach as root 1`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k1, v1, l1, c1] = prepareList(ctx['items']);
for (let i1 = 0; i1 < l1; i1++) {
ctx[\`item\`] = v1[i1];
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['items']);
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`item\`] = v_block1[i1];
let key1 = ctx['item'];
c1[i1] = withKey(text(ctx['item']), key1);
c_block1[i1] = withKey(text(ctx['item']), key1);
}
return list(c1);
return list(c_block1);
}
}"
`;
@@ -1030,15 +1030,15 @@ exports[`basics widget after a t-foreach 2`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(Array(2));
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`elem\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(2));
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`elem\`] = v_block2[i1];
ctx[\`elem_index\`] = i1;
let key1 = ctx['elem_index'];
c2[i1] = withKey(text(\`txt\`), key1);
c_block2[i1] = withKey(text(\`txt\`), key1);
}
ctx = ctx.__proto__;
let b2 = list(c2);
let b2 = list(c_block2);
let b4 = component(\`SomeComponent\`, {}, key + \`__1\`, node, ctx);
return block1([], [b2, b4]);
}
@@ -1502,15 +1502,15 @@ exports[`slots slots are rendered with proper context, part 2 2`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(ctx['state'].users);
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`user\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].users);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`user\`] = v_block2[i1];
let key1 = ctx['user'].id;
const ctx2 = capture(ctx);
let b7 = assign(component(\`Link\`, {to: '/user/'+ctx['user'].id}, key + \`__1__\${key1}\`, node, ctx), {slots: {'default': slot3(ctx2)}});
c2[i1] = withKey(block3([], [b7]), key1);
c_block2[i1] = withKey(block3([], [b7]), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -1549,16 +1549,16 @@ exports[`slots slots are rendered with proper context, part 3 2`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(ctx['state'].users);
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`user\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].users);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`user\`] = v_block2[i1];
let key1 = ctx['user'].id;
ctx[\`userdescr\`] = 'User '+ctx['user'].name;
const ctx2 = capture(ctx);
let b5 = assign(component(\`Link\`, {to: '/user/'+ctx['user'].id}, key + \`__1__\${key1}\`, node, ctx), {slots: {'default': slot3(ctx2)}});
c2[i1] = withKey(block3([], [b5]), key1);
c_block2[i1] = withKey(block3([], [b5]), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -1694,15 +1694,15 @@ exports[`slots slots in t-foreach and re-rendering 2`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(Array(2));
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`n\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(2));
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`n\`] = v_block2[i1];
ctx[\`n_index\`] = i1;
let key1 = ctx['n_index'];
const ctx2 = capture(ctx);
c2[i1] = withKey(assign(component(\`Child\`, {}, key + \`__1__\${key1}\`, node, ctx), {slots: {'default': slot3(ctx2)}}), key1);
c_block2[i1] = withKey(assign(component(\`Child\`, {}, key + \`__1__\${key1}\`, node, ctx), {slots: {'default': slot3(ctx2)}}), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -1742,26 +1742,26 @@ exports[`slots slots in t-foreach in t-foreach 2`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(ctx['tree']);
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`node1\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['tree']);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`node1\`] = v_block2[i1];
let key1 = ctx['node1'].key;
let d1 = ctx['node1'].value;
let b4 = block4([d1]);
ctx = Object.create(ctx);
const [k6, v6, l6, c6] = prepareList(ctx['node1'].nodes);
for (let i2 = 0; i2 < l6; i2++) {
ctx[\`node2\`] = v6[i2];
const [k_block6, v_block6, l_block6, c_block6] = prepareList(ctx['node1'].nodes);
for (let i2 = 0; i2 < l_block6; i2++) {
ctx[\`node2\`] = v_block6[i2];
let key2 = ctx['node2'].key;
const ctx2 = capture(ctx);
c6[i2] = withKey(assign(component(\`Child\`, {}, key + \`__1__\${key1}__\${key2}\`, node, ctx), {slots: {'default': slot3(ctx2)}}), key2);
c_block6[i2] = withKey(assign(component(\`Child\`, {}, key + \`__1__\${key1}__\${key2}\`, node, ctx), {slots: {'default': slot3(ctx2)}}), key2);
}
ctx = ctx.__proto__;
let b6 = list(c6);
let b6 = list(c_block6);
let b5 = block5([], [b6]);
c2[i1] = withKey(multi([b4, b5]), key1);
c_block2[i1] = withKey(multi([b4, b5]), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -1799,16 +1799,16 @@ exports[`slots slots in t-foreach with t-set and re-rendering 2`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(Array(2));
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`n\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(2));
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`n\`] = v_block2[i1];
ctx[\`n_index\`] = i1;
let key1 = ctx['n_index'];
ctx[\`dummy\`] = ctx['n_index'];
const ctx2 = capture(ctx);
c2[i1] = withKey(assign(component(\`Child\`, {}, key + \`__1__\${key1}\`, node, ctx), {slots: {'default': slot3(ctx2)}}), key1);
c_block2[i1] = withKey(assign(component(\`Child\`, {}, key + \`__1__\${key1}\`, node, ctx), {slots: {'default': slot3(ctx2)}}), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -1915,13 +1915,13 @@ exports[`slots t-slot in recursive templates 2`] = `
const slot3 = ctx => (node, key) => {
let b2 = text(ctx['name']);
ctx = Object.create(ctx);
const [k3, v3, l3, c3] = prepareList(ctx['items']);
for (let i1 = 0; i1 < l3; i1++) {
ctx[\`item\`] = v3[i1];
const [k_block3, v_block3, l_block3, c_block3] = prepareList(ctx['items']);
for (let i1 = 0; i1 < l_block3; i1++) {
ctx[\`item\`] = v_block3[i1];
ctx[\`item_first\`] = i1 === 0;
ctx[\`item_last\`] = i1 === v3.length - 1;
ctx[\`item_last\`] = i1 === v_block3.length - 1;
ctx[\`item_index\`] = i1;
ctx[\`item_value\`] = k3[i1];
ctx[\`item_value\`] = k_block3[i1];
let key1 = ctx['item'].name;
let b5,b6;
if (!ctx['item'].children.length) {
@@ -1933,10 +1933,10 @@ exports[`slots t-slot in recursive templates 2`] = `
b6 = callTemplate_5(ctx, node, key + \`__4__\${key1}\`);
ctx = ctx.__proto__;
}
c3[i1] = withKey(multi([b5, b6]), key1);
c_block3[i1] = withKey(multi([b5, b6]), key1);
}
ctx = ctx.__proto__;
let b3 = list(c3);
let b3 = list(c_block3);
return multi([b2, b3]);
}
@@ -275,17 +275,17 @@ exports[`t-call t-call in t-foreach and children component 3`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(['a','b','c']);
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`val\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(['a','b','c']);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`val\`] = v_block2[i1];
ctx[\`val_first\`] = i1 === 0;
ctx[\`val_last\`] = i1 === v2.length - 1;
ctx[\`val_last\`] = i1 === v_block2.length - 1;
ctx[\`val_index\`] = i1;
ctx[\`val_value\`] = k2[i1];
ctx[\`val_value\`] = k_block2[i1];
let key1 = ctx['val'];
c2[i1] = withKey(callTemplate_2(ctx, node, key + \`__1__\${key1}\`), key1);
c_block2[i1] = withKey(callTemplate_2(ctx, node, key + \`__1__\${key1}\`), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -26,14 +26,14 @@ exports[`list of components components in a node in a t-foreach 2`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(ctx['items']);
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`item\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['items']);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`item\`] = v_block2[i1];
let key1 = 'li_'+ctx['item'];
let b4 = component(\`Child\`, {item: ctx['item']}, key + \`__1__\${key1}\`, node, ctx);
c2[i1] = withKey(block3([], [b4]), key1);
c_block2[i1] = withKey(block3([], [b4]), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -64,14 +64,14 @@ exports[`list of components list of sub components inside other nodes 2`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(ctx['state'].blips);
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`blip\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].blips);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`blip\`] = v_block2[i1];
let key1 = ctx['blip'].id;
let b4 = component(\`SubComponent\`, {}, key + \`__1__\${key1}\`, node, ctx);
c2[i1] = withKey(block3([], [b4]), key1);
c_block2[i1] = withKey(block3([], [b4]), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -102,23 +102,23 @@ exports[`list of components reconciliation alg works for t-foreach in t-foreach
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(ctx['state'].s);
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`section\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].s);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`section\`] = v_block2[i1];
ctx[\`section_index\`] = i1;
let key1 = ctx['section_index'];
ctx = Object.create(ctx);
const [k3, v3, l3, c3] = prepareList(ctx['section'].blips);
for (let i2 = 0; i2 < l3; i2++) {
ctx[\`blip\`] = v3[i2];
const [k_block3, v_block3, l_block3, c_block3] = prepareList(ctx['section'].blips);
for (let i2 = 0; i2 < l_block3; i2++) {
ctx[\`blip\`] = v_block3[i2];
ctx[\`blip_index\`] = i2;
let key2 = ctx['blip_index'];
c3[i2] = withKey(component(\`Child\`, {blip: ctx['blip']}, key + \`__1__\${key1}__\${key2}\`, node, ctx), key2);
c_block3[i2] = withKey(component(\`Child\`, {blip: ctx['blip']}, key + \`__1__\${key1}__\${key2}\`, node, ctx), key2);
}
ctx = ctx.__proto__;
c2[i1] = withKey(list(c3), key1);
c_block2[i1] = withKey(list(c_block3), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -151,23 +151,23 @@ exports[`list of components reconciliation alg works for t-foreach in t-foreach,
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(ctx['state'].rows);
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`row\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].rows);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`row\`] = v_block2[i1];
let key1 = ctx['row'];
ctx = Object.create(ctx);
const [k4, v4, l4, c4] = prepareList(ctx['state'].cols);
for (let i2 = 0; i2 < l4; i2++) {
ctx[\`col\`] = v4[i2];
const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['state'].cols);
for (let i2 = 0; i2 < l_block4; i2++) {
ctx[\`col\`] = v_block4[i2];
let key2 = ctx['col'];
let b6 = component(\`Child\`, {row: ctx['row'],col: ctx['col']}, key + \`__1__\${key1}__\${key2}\`, node, ctx);
c4[i2] = withKey(block5([], [b6]), key2);
c_block4[i2] = withKey(block5([], [b6]), key2);
}
ctx = ctx.__proto__;
let b4 = list(c4);
c2[i1] = withKey(block3([], [b4]), key1);
let b4 = list(c_block4);
c_block2[i1] = withKey(block3([], [b4]), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -196,13 +196,13 @@ exports[`list of components simple list 2`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k1, v1, l1, c1] = prepareList(ctx['state'].elems);
for (let i1 = 0; i1 < l1; i1++) {
ctx[\`elem\`] = v1[i1];
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['state'].elems);
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`elem\`] = v_block1[i1];
let key1 = ctx['elem'].id;
c1[i1] = withKey(component(\`Child\`, {value: ctx['elem'].value}, key + \`__1__\${key1}\`, node, ctx), key1);
c_block1[i1] = withKey(component(\`Child\`, {value: ctx['elem'].value}, key + \`__1__\${key1}\`, node, ctx), key1);
}
return list(c1);
return list(c_block1);
}
}"
`;
@@ -232,13 +232,13 @@ exports[`list of components sub components rendered in a loop 2`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(ctx['state'].numbers);
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`number\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].numbers);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`number\`] = v_block2[i1];
let key1 = ctx['number'];
c2[i1] = withKey(component(\`Child\`, {n: ctx['number']}, key + \`__1__\${key1}\`, node, ctx), key1);
c_block2[i1] = withKey(component(\`Child\`, {n: ctx['number']}, key + \`__1__\${key1}\`, node, ctx), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -269,13 +269,13 @@ exports[`list of components sub components with some state rendered in a loop 2`
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(ctx['state'].numbers);
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`number\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].numbers);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`number\`] = v_block2[i1];
let key1 = ctx['number'];
c2[i1] = withKey(component(\`Child\`, {}, key + \`__1__\${key1}\`, node, ctx), key1);
c_block2[i1] = withKey(component(\`Child\`, {}, key + \`__1__\${key1}\`, node, ctx), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -307,14 +307,14 @@ exports[`list of components t-foreach with t-component, and update 2`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k2, v2, l2, c2] = prepareList(Array(2));
for (let i1 = 0; i1 < l2; i1++) {
ctx[\`n\`] = v2[i1];
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(2));
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`n\`] = v_block2[i1];
ctx[\`n_index\`] = i1;
let key1 = ctx['n_index'];
c2[i1] = withKey(component(\`Child\`, {val: ctx['n_index']}, key + \`__1__\${key1}\`, node, ctx), key1);
c_block2[i1] = withKey(component(\`Child\`, {val: ctx['n_index']}, key + \`__1__\${key1}\`, node, ctx), key1);
}
let b2 = list(c2);
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
@@ -0,0 +1,153 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`t-on t-on expression captured in t-foreach 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, shallowEqual } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div><button block-handler-0=\\"click\\">expr</button></div>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[\`iter\`] = 0;
ctx = Object.create(ctx);
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['arr']);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`val\`] = v_block2[i1];
let key1 = ctx['val'];
const v1 = ctx['otherState'];
const v2 = ctx['iter'];
let d1 = (e) => {const res = (() => { return v1.vals.push(v2+'_'+v2) })(); if (typeof res === 'function') { res(e) }};
ctx[\`iter\`] = ctx['iter']+1;
c_block2[i1] = withKey(block3([d1]), key1);
}
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
`;
exports[`t-on t-on expression in t-foreach 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, shallowEqual } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div><block-text-0/>: <block-text-1/><button block-handler-2=\\"click\\">Expr</button></div>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].values);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`val\`] = v_block2[i1];
ctx[\`val_index\`] = i1;
let key1 = ctx['val'];
let d1 = ctx['val_index'];
let d2 = ctx['val']+'';
const v1 = ctx['otherState'];
const v2 = ctx['val'];
let d3 = (e) => {const res = (() => { return v1.vals.push(v2) })(); if (typeof res === 'function') { res(e) }};
c_block2[i1] = withKey(block3([d1, d2, d3]), key1);
}
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
`;
exports[`t-on t-on expression in t-foreach with t-set 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, shallowEqual } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div><block-text-0/>: <block-text-1/><button block-handler-2=\\"click\\">Expr</button></div>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[\`bossa\`] = 'nova';
ctx = Object.create(ctx);
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].values);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`val\`] = v_block2[i1];
ctx[\`val_index\`] = i1;
let key1 = ctx['val'];
ctx[\`bossa\`] = ctx['bossa']+'_'+ctx['val_index'];
let d1 = ctx['val_index'];
let d2 = ctx['val']+'';
const v1 = ctx['otherState'];
const v2 = ctx['val'];
const v3 = ctx['bossa'];
let d3 = (e) => {const res = (() => { return v1.vals.push(v2+'_'+v3) })(); if (typeof res === 'function') { res(e) }};
c_block2[i1] = withKey(block3([d1, d2, d3]), key1);
}
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
`;
exports[`t-on t-on method call in t-foreach 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, shallowEqual } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div><block-text-0/>: <block-text-1/><button block-handler-2=\\"click\\">meth call</button></div>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].values);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`val\`] = v_block2[i1];
ctx[\`val_index\`] = i1;
let key1 = ctx['val'];
let d1 = ctx['val_index'];
let d2 = ctx['val']+'';
const arg1 = [ctx['val']];
let d3 = [ctx, 'addVal', arg1];
c_block2[i1] = withKey(block3([d1, d2, d3]), key1);
}
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
`;
exports[`t-on t-on on destroyed components 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, shallowEqual } = helpers;
let block1 = createBlock(\`<div block-handler-0=\\"click\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = [ctx, 'onClick'];
return block1([d1]);
}
}"
`;
exports[`t-on t-on on destroyed components 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, shallowEqual } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2;
if (ctx['state'].flag) {
b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
}
return block1([], [b2]);
}
}"
`;
+3 -1
View File
@@ -718,7 +718,9 @@ describe("basics", () => {
await nextTick();
expect(Object.values(parent.__owl__.children)[0].component).toBe(child);
expect(status(child)).toBe("mounted");
expect(fixture.innerHTML).toBe(`<div><h1>hey</h1><span><span>child</span></span><span>test</span></div>`)
expect(fixture.innerHTML).toBe(
`<div><h1>hey</h1><span><span>child</span></span><span>test</span></div>`
);
});
test("list of two sub components inside other nodes", async () => {
+3 -1
View File
@@ -919,7 +919,9 @@ describe("lifecycle hooks", () => {
static template = xml`<div/>`;
setup() {
created = true;
onMounted(() => { mounted = true; })
onMounted(() => {
mounted = true;
});
}
}
class Parent extends Component {
+4 -3
View File
@@ -244,7 +244,7 @@ describe("style and class handling", () => {
state = useState({ d: true });
}
class Parent extends Component {
static template = xml`<Child class="a" t-att-class="state.b ? 'b' : ''" t-ref="child"/>`
static template = xml`<Child class="a" t-att-class="state.b ? 'b' : ''" t-ref="child"/>`;
static components = { Child };
state = useState({ b: true });
child = useRef("child");
@@ -319,7 +319,7 @@ describe("style and class handling", () => {
expect(fixture.innerHTML).toBe(`<div t-att-style="font-size: 20px;"></div>`);
widget.state.style["font-size"] = "30px" ;
widget.state.style["font-size"] = "30px";
await nextTick();
expect(fixture.innerHTML).toBe(`<div style="font-size: 30px;"></div>`);
@@ -341,7 +341,8 @@ describe("style and class handling", () => {
error = e;
}
expect(error).toBeDefined();
const regexp = /Cannot read properties of undefined \(reading 'crash'\)|Cannot read property 'crash' of undefined/g;
const regexp =
/Cannot read properties of undefined \(reading 'crash'\)|Cannot read property 'crash' of undefined/g;
expect(error.message).toMatch(regexp);
expect(fixture.innerHTML).toBe("");
});
+145
View File
@@ -0,0 +1,145 @@
import { Component, mount, onMounted, useState, xml } from "../../src/index";
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers";
import { status } from "../../src/component/status";
snapshotEverything();
let fixture: HTMLElement;
beforeEach(() => {
fixture = makeTestFixture();
});
describe("t-on", () => {
test("t-on on destroyed components", async () => {
const steps: string[] = [];
let child;
class Child extends Component {
static template = xml`<div t-on-click="onClick"/>`;
setup() {
onMounted(() => {
child = this;
});
}
onClick() {
steps.push("click");
}
}
class Parent extends Component {
static template = xml`<div><Child t-if="state.flag"/></div>`;
static components = { Child };
state = useState({ flag: true });
}
const parent = await mount(Parent, fixture);
let el = (child as any).el as HTMLElement;
el.click();
expect(steps).toEqual(["click"]);
(parent as any).state.flag = false;
await nextTick();
expect(status(child as any)).toBe("destroyed");
el.click();
expect(steps).toEqual(["click"]);
});
test("t-on expression in t-foreach", async () => {
class Comp extends Component {
static template = xml`
<div>
<div t-foreach="state.values" t-as="val" t-key="val">
<t t-esc="val_index"/>: <t t-esc="val + ''"/>
<button t-on-click="otherState.vals.push(val)">Expr</button>
</div>
</div>
`;
state = useState({ values: ["a", "b"] });
otherState = { vals: [] };
}
const comp = await mount(Comp, fixture);
expect(fixture.innerHTML).toBe(
"<div><div>0: a<button>Expr</button></div><div>1: b<button>Expr</button></div></div>"
);
expect(comp.otherState.vals).toStrictEqual([]);
const buttons = fixture.querySelectorAll("button");
buttons[0].click();
buttons[1].click();
expect(comp.otherState.vals).toStrictEqual(["a", "b"]);
});
test("t-on expression in t-foreach with t-set", async () => {
class Comp extends Component {
static template = xml`
<div>
<t t-set="bossa" t-value="'nova'"/>
<div t-foreach="state.values" t-as="val" t-key="val">
<t t-set="bossa" t-value="bossa + '_' + val_index" />
<t t-esc="val_index"/>: <t t-esc="val + ''"/>
<button t-on-click="otherState.vals.push(val + '_' + bossa)">Expr</button>
</div>
</div>
`;
state = useState({ values: ["a", "b"] });
otherState = { vals: [] };
}
const comp = await mount(Comp, fixture);
expect(fixture.innerHTML).toBe(
"<div><div>0: a<button>Expr</button></div><div>1: b<button>Expr</button></div></div>"
);
expect(comp.otherState.vals).toStrictEqual([]);
const buttons = fixture.querySelectorAll("button");
buttons[0].click();
buttons[1].click();
expect(comp.otherState.vals).toStrictEqual(["a_nova_0", "b_nova_0_1"]);
});
test("t-on method call in t-foreach", async () => {
class Comp extends Component {
static template = xml`
<div>
<div t-foreach="state.values" t-as="val" t-key="val">
<t t-esc="val_index"/>: <t t-esc="val + ''"/>
<button t-on-click="addVal(val)">meth call</button>
</div>
</div>
`;
state = useState({ values: ["a", "b"] });
otherState = { vals: new Array<string>() };
addVal(val: string) {
this.otherState.vals.push(val);
}
}
const comp = await mount(Comp, fixture);
expect(fixture.innerHTML).toBe(
"<div><div>0: a<button>meth call</button></div><div>1: b<button>meth call</button></div></div>"
);
expect(comp.otherState.vals).toStrictEqual([]);
const buttons = fixture.querySelectorAll("button");
buttons[0].click();
buttons[1].click();
expect(comp.otherState.vals).toStrictEqual(["a", "b"]);
});
test("t-on expression captured in t-foreach", async () => {
class Comp extends Component {
static template = xml`
<div>
<t t-set="iter" t-value="0" />
<div t-foreach="arr" t-as="val" t-key="val">
<button t-on-click="otherState.vals.push(iter + '_' + iter)">expr</button>
<t t-set="iter" t-value="iter + 1" />
</div>
</div>
`;
arr = ["a", "b"];
otherState = { vals: new Array<string>() };
}
const comp = await mount(Comp, fixture);
expect(fixture.innerHTML).toBe(
"<div><div><button>expr</button></div><div><button>expr</button></div></div>"
);
expect(comp.otherState.vals).toStrictEqual([]);
const buttons = fixture.querySelectorAll("button");
buttons[0].click();
buttons[1].click();
expect(comp.otherState.vals).toStrictEqual(["0_0", "1_1"]);
});
});