mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] qweb: compiler: support t-key on node and component without t-foreach
This commit is contained in:
committed by
Géry Debongnie
parent
779fc6b02b
commit
ae71db28e4
@@ -54,4 +54,61 @@ describe("togglers", () => {
|
||||
expect(fixture.innerHTML).toBe("<p>hey</p>");
|
||||
expect(fixture.firstChild).not.toBe(textnode);
|
||||
});
|
||||
|
||||
test("beforeRemove is called", () => {
|
||||
const block = createBlock("<p>hey</p>");
|
||||
|
||||
function blockOverriden() {
|
||||
const vn = block();
|
||||
vn.beforeRemove = () => {
|
||||
steps.push("beforeRemove");
|
||||
};
|
||||
return vn;
|
||||
}
|
||||
|
||||
const steps: string[] = [];
|
||||
const tree = toggler("key1", blockOverriden());
|
||||
mount(tree, fixture);
|
||||
expect(fixture.innerHTML).toBe("<p>hey</p>");
|
||||
patch(tree, toggler("key2", text("foo")));
|
||||
expect(fixture.innerHTML).toBe("foo");
|
||||
|
||||
patch(tree, toggler("key3", blockOverriden()), true);
|
||||
expect(fixture.innerHTML).toBe("<p>hey</p>");
|
||||
|
||||
patch(tree, toggler("key2", text("foo")), true);
|
||||
expect(fixture.innerHTML).toBe("foo");
|
||||
|
||||
expect(steps).toEqual(["beforeRemove"]);
|
||||
});
|
||||
|
||||
test("beforeRemove is called when within a block", () => {
|
||||
const block = createBlock("<p><block-child-0/></p>");
|
||||
const conditionalBlock = createBlock("<p>hey</p>");
|
||||
|
||||
const steps: string[] = [];
|
||||
|
||||
function blockOverriden() {
|
||||
const vn = conditionalBlock();
|
||||
vn.beforeRemove = function () {
|
||||
steps.push("beforeRemove");
|
||||
};
|
||||
return vn;
|
||||
}
|
||||
const mainBlock = block([], [toggler("key1", blockOverriden())]);
|
||||
|
||||
mount(mainBlock, fixture);
|
||||
expect(fixture.innerHTML).toBe("<p><p>hey</p></p>");
|
||||
|
||||
patch(mainBlock, block([], []));
|
||||
expect(fixture.innerHTML).toBe("<p></p>");
|
||||
|
||||
patch(mainBlock, block([], [toggler("key1", blockOverriden())]), true);
|
||||
expect(fixture.innerHTML).toBe("<p><p>hey</p></p>");
|
||||
|
||||
patch(mainBlock, block([], []), true);
|
||||
expect(fixture.innerHTML).toBe("<p></p>");
|
||||
|
||||
expect(steps).toEqual(["beforeRemove"]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -581,7 +581,8 @@ exports[`basics reconciliation alg is not confused in some specific situation 2`
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
|
||||
let b3 = component(\`Child\`, {}, key + \`__2\`, node, ctx);
|
||||
const tKey_2 = 4;
|
||||
let b3 = toggler(tKey_2, component(\`Child\`, {}, tKey_2 + key + \`__3\`, node, ctx));
|
||||
return block1([], [b2, b3]);
|
||||
}
|
||||
}"
|
||||
@@ -640,8 +641,10 @@ exports[`basics same t-keys in two different places 2`] = `
|
||||
let block1 = createBlock(\`<div><div><block-child-0/></div><div><block-child-1/></div></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let b2 = component(\`Child\`, {blip: '1'}, key + \`__1\`, node, ctx);
|
||||
let b3 = component(\`Child\`, {blip: '2'}, key + \`__2\`, node, ctx);
|
||||
const tKey_1 = 1;
|
||||
let b2 = toggler(tKey_1, component(\`Child\`, {blip: '1'}, tKey_1 + key + \`__2\`, node, ctx));
|
||||
const tKey_3 = 1;
|
||||
let b3 = toggler(tKey_3, component(\`Child\`, {blip: '2'}, tKey_3 + key + \`__4\`, node, ctx));
|
||||
return block1([], [b2, b3]);
|
||||
}
|
||||
}"
|
||||
@@ -889,14 +892,15 @@ exports[`basics t-key on a component with t-if, and a sibling component 2`] = `
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
|
||||
let block1 = createBlock(\`<div><block-child-0/><block-child-0/><block-child-1/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let b2,b3;
|
||||
if (false) {
|
||||
b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
|
||||
const tKey_1 = 'str';
|
||||
b2 = toggler(tKey_1, component(\`Child\`, {}, tKey_1 + key + \`__2\`, node, ctx));
|
||||
}
|
||||
b3 = component(\`Child\`, {}, key + \`__2\`, node, ctx);
|
||||
b3 = component(\`Child\`, {}, key + \`__3\`, node, ctx);
|
||||
return block1([], [b2, b3]);
|
||||
}
|
||||
}"
|
||||
|
||||
@@ -18,7 +18,7 @@ exports[`calling render in destroy 1`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, inTCall, shallowEqual, setContextValue } = helpers;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-text-0/></div>\`);
|
||||
|
||||
@@ -33,7 +33,7 @@ exports[`calling render in destroy 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 { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
return component(\`C\`, {fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx);
|
||||
@@ -45,10 +45,11 @@ exports[`calling render in destroy 3`] = `
|
||||
"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 { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
return component(\`B\`, {fromA: ctx['state']}, key + \`__1\`, node, ctx);
|
||||
const tKey_1 = ctx['key'];
|
||||
return toggler(tKey_1, component(\`B\`, {fromA: ctx['state']}, tKey_1 + key + \`__2\`, node, ctx));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@@ -1159,12 +1160,13 @@ exports[`two renderings initiated between willPatch and patched 2`] = `
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||
let block1 = createBlock(\`<div><block-child-0/><block-child-0/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let b2;
|
||||
if (ctx['state'].flag) {
|
||||
b2 = component(\`Panel\`, {val: ctx['state'].panel}, key + \`__1\`, node, ctx);
|
||||
const tKey_1 = 'panel_'+ctx['state'].panel;
|
||||
b2 = toggler(tKey_1, component(\`Panel\`, {val: ctx['state'].panel}, tKey_1 + key + \`__2\`, node, ctx));
|
||||
}
|
||||
return block1([], [b2]);
|
||||
}
|
||||
|
||||
@@ -79,8 +79,9 @@ exports[`t-component can use dynamic components (the class) if given (with diffe
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let Comp2 = ctx['myComponent'];
|
||||
return toggler(Comp2, component(Comp2, {}, key + \`__1\`, node, ctx));
|
||||
const tKey_1 = ctx['state'].child;
|
||||
let Comp3 = ctx['myComponent'];
|
||||
return toggler(tKey_1, toggler(Comp3, component(Comp3, {}, tKey_1 + key + \`__2\`, node, ctx)));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@@ -120,8 +121,9 @@ exports[`t-component can use dynamic components (the class) if given 3`] = `
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let Comp2 = ctx['myComponent'];
|
||||
return toggler(Comp2, component(Comp2, {}, key + \`__1\`, node, ctx));
|
||||
const tKey_1 = ctx['state'].child;
|
||||
let Comp3 = ctx['myComponent'];
|
||||
return toggler(tKey_1, toggler(Comp3, component(Comp3, {}, tKey_1 + key + \`__2\`, node, ctx)));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
@@ -281,6 +281,43 @@ exports[`list of components sub components with some state rendered in a loop 2`
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`list of components switch component position 1`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-text-0/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let d1 = ctx['props'].key;
|
||||
return block1([d1]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`list of components switch component position 2`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<span><block-child-0/></span>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['clist']);
|
||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||
ctx[\`c\`] = v_block2[i1];
|
||||
let key1 = ctx['c'];
|
||||
c_block2[i1] = withKey(component(\`Child\`, {key: ctx['c']}, key + \`__1__\${key1}\`, node, ctx), key1);
|
||||
}
|
||||
let b2 = list(c_block2);
|
||||
return block1([], [b2]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`list of components t-foreach with t-component, and update 1`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`t-key t-foreach with t-key switch component position 1`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-text-0/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let d1 = ctx['props'].key;
|
||||
return block1([d1]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-foreach with t-key switch component position 2`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<span><block-child-0/></span>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['clist']);
|
||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||
ctx[\`c\`] = v_block2[i1];
|
||||
let key1 = ctx['c'];
|
||||
const tKey_1 = ctx['key1'];
|
||||
c_block2[i1] = withKey(component(\`Child\`, {key: ctx['c']+ctx['key1']}, tKey_1 + key + \`__2__\${key1}\`, node, ctx), tKey_1 + key1);
|
||||
}
|
||||
let b2 = list(c_block2);
|
||||
return block1([], [b2]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-key on Component 1`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-text-0/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let d1 = ctx['props'].key;
|
||||
return block1([d1]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-key on Component 2`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<span><block-child-0/></span>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const tKey_1 = ctx['key'];
|
||||
let b2 = toggler(tKey_1, component(\`Child\`, {key: ctx['key']}, tKey_1 + key + \`__2\`, node, ctx));
|
||||
return block1([], [b2]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-key on Component as a function 1`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-text-0/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let d1 = ctx['props'].key;
|
||||
return block1([d1]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-key on Component as a function 2`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<span><block-child-0/></span>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const tKey_1 = ctx['key'];
|
||||
let b2 = toggler(tKey_1, component(\`Child\`, {key: ctx['key']}, tKey_1 + key + \`__2\`, node, ctx));
|
||||
return block1([], [b2]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-key on multiple Components 1`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-text-0/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let d1 = ctx['props'].key;
|
||||
return block1([d1]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-key on multiple Components 2`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<span><block-child-0/><block-child-1/></span>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const tKey_1 = ctx['key1'];
|
||||
let b2 = toggler(tKey_1, component(\`Child\`, {key: ctx['key1']}, tKey_1 + key + \`__2\`, node, ctx));
|
||||
const tKey_3 = ctx['key2'];
|
||||
let b3 = toggler(tKey_3, component(\`Child\`, {key: ctx['key2']}, tKey_3 + key + \`__4\`, node, ctx));
|
||||
return block1([], [b2, b3]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-key on multiple Components with t-call 1 1`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-text-0/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let d1 = ctx['props'].key;
|
||||
return block1([d1]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-key on multiple Components with t-call 1 2`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const tKey_1 = ctx['key'];
|
||||
return toggler(tKey_1, component(\`Child\`, {key: ctx['key']}, tKey_1 + key + \`__2\`, node, ctx));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-key on multiple Components with t-call 1 3`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
const callTemplate_2 = getTemplate(\`calledTemplate\`);
|
||||
const callTemplate_4 = getTemplate(\`calledTemplate\`);
|
||||
|
||||
let block1 = createBlock(\`<span><block-child-0/><block-child-1/></span>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
ctx[isBoundary] = 1
|
||||
ctx = Object.create(ctx);
|
||||
ctx[isBoundary] = 1;
|
||||
setContextValue(ctx, \\"key\\", ctx['key1']);
|
||||
let b2 = callTemplate_2(ctx, node, key + \`__1\`);
|
||||
ctx = ctx.__proto__;
|
||||
ctx = Object.create(ctx);
|
||||
ctx[isBoundary] = 1;
|
||||
setContextValue(ctx, \\"key\\", ctx['key2']);
|
||||
let b3 = callTemplate_4(ctx, node, key + \`__3\`);
|
||||
return block1([], [b2, b3]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-key on multiple Components with t-call 2 1`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-text-0/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let d1 = ctx['props'].key;
|
||||
return block1([d1]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-key on multiple Components with t-call 2 2`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const tKey_1 = ctx['key1'];
|
||||
let b2 = toggler(tKey_1, component(\`Child\`, {key: ctx['key1']}, tKey_1 + key + \`__2\`, node, ctx));
|
||||
const tKey_3 = ctx['key2'];
|
||||
let b3 = toggler(tKey_3, component(\`Child\`, {key: ctx['key2']}, tKey_3 + key + \`__4\`, node, ctx));
|
||||
return multi([b2, b3]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key t-key on multiple Components with t-call 2 3`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
const callTemplate_2 = getTemplate(\`calledTemplate\`);
|
||||
|
||||
let block1 = createBlock(\`<span><block-child-0/></span>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
let b2 = callTemplate_2(ctx, node, key + \`__1\`);
|
||||
return block1([], [b2]);
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@@ -2108,7 +2108,7 @@ test("concurrent renderings scenario 16", async () => {
|
||||
// });
|
||||
|
||||
// TODO: unskip when t-key is reimplemented properly
|
||||
test.skip("calling render in destroy", async () => {
|
||||
test("calling render in destroy", async () => {
|
||||
const steps: any[] = [];
|
||||
|
||||
let a: any = null;
|
||||
@@ -2165,7 +2165,7 @@ test.skip("calling render in destroy", async () => {
|
||||
// this nextTick is critical, otherwise jest may silently swallow errors
|
||||
await nextTick();
|
||||
|
||||
expect(steps).toBe(["B:mounted", "B:willUnmount", "B:mounted"]);
|
||||
expect(steps).toStrictEqual(["B:mounted", "B:willUnmount", "B:mounted"]);
|
||||
expect(fixture.innerHTML).toBe("<div>A</div>");
|
||||
});
|
||||
|
||||
@@ -2302,7 +2302,7 @@ test("render method wait until rendering is done", async () => {
|
||||
|
||||
test("two renderings initiated between willPatch and patched", async () => {
|
||||
let parent: any = null;
|
||||
let steps: string[] = [];
|
||||
const steps: string[] = [];
|
||||
|
||||
class Panel extends Component {
|
||||
static template = xml`<abc><t t-esc="props.val"/></abc>`;
|
||||
@@ -2325,17 +2325,8 @@ test("two renderings initiated between willPatch and patched", async () => {
|
||||
}
|
||||
|
||||
await mount(Parent, fixture);
|
||||
|
||||
expect(fixture.innerHTML).toBe("<div><abc>Panel1</abc></div>");
|
||||
|
||||
parent.state.panel = "Panel2";
|
||||
await nextTick();
|
||||
expect(fixture.innerHTML).toBe("<div><abc>Panel2</abc></div>");
|
||||
|
||||
parent.state.flag = false;
|
||||
await nextTick();
|
||||
expect(fixture.innerHTML).toBe("<div></div>");
|
||||
|
||||
expect(steps).toEqual([
|
||||
"Parent:setup",
|
||||
"Parent:willStart",
|
||||
@@ -2345,13 +2336,31 @@ test("two renderings initiated between willPatch and patched", async () => {
|
||||
"Panel:render",
|
||||
"Panel:mounted",
|
||||
"Parent:mounted",
|
||||
]);
|
||||
steps.length = 0;
|
||||
|
||||
parent.state.panel = "Panel2";
|
||||
await nextTick();
|
||||
expect(fixture.innerHTML).toBe("<div><abc>Panel2</abc></div>");
|
||||
|
||||
expect(steps).toEqual([
|
||||
"Parent:render",
|
||||
"Panel:willUpdateProps",
|
||||
"Panel:setup",
|
||||
"Panel:willStart",
|
||||
"Panel:render",
|
||||
"Parent:willPatch",
|
||||
"Panel:willPatch",
|
||||
"Panel:patched",
|
||||
"Panel:willUnmount",
|
||||
"Panel:destroyed",
|
||||
"Panel:mounted",
|
||||
"Parent:patched",
|
||||
]);
|
||||
steps.length = 0;
|
||||
|
||||
parent.state.flag = false;
|
||||
await nextTick();
|
||||
expect(fixture.innerHTML).toBe("<div></div>");
|
||||
|
||||
expect(steps).toEqual([
|
||||
"Parent:render",
|
||||
"Parent:willPatch",
|
||||
"Panel:willUnmount",
|
||||
|
||||
@@ -43,8 +43,7 @@ describe("basics", () => {
|
||||
expect(fixture.innerHTML).toBe("");
|
||||
expect(status(parent)).toBe("destroyed");
|
||||
expect(error).toBeDefined();
|
||||
const regexp =
|
||||
/Cannot read properties of undefined \(reading 'this'\)|Cannot read property 'this' of undefined/g;
|
||||
const regexp = /Cannot read properties of undefined \(reading 'this'\)|Cannot read property 'this' of undefined/g;
|
||||
expect(error.message).toMatch(regexp);
|
||||
});
|
||||
|
||||
@@ -113,8 +112,7 @@ describe.skip("errors and promises", () => {
|
||||
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(console.error).toBeCalledTimes(0);
|
||||
@@ -227,8 +225,7 @@ describe.skip("errors and promises", () => {
|
||||
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(console.error).toBeCalledTimes(0);
|
||||
@@ -254,8 +251,7 @@ describe.skip("errors and promises", () => {
|
||||
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(console.error).toBeCalledTimes(0);
|
||||
@@ -278,8 +274,7 @@ describe.skip("errors and promises", () => {
|
||||
error = e;
|
||||
}
|
||||
expect(error).toBeDefined();
|
||||
const regexp =
|
||||
/Cannot read properties of undefined \(reading 'y'\)|Cannot read property 'y' of undefined/g;
|
||||
const regexp = /Cannot read properties of undefined \(reading 'y'\)|Cannot read property 'y' of undefined/g;
|
||||
expect(error.message).toMatch(regexp);
|
||||
});
|
||||
|
||||
|
||||
@@ -341,8 +341,7 @@ 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("");
|
||||
});
|
||||
|
||||
@@ -260,4 +260,32 @@ describe("list of components", () => {
|
||||
await nextTick(); // wait for changes triggered in mounted to be applied
|
||||
expect(fixture.innerHTML).toBe("<div><span>B0</span><span>B1</span></div>");
|
||||
});
|
||||
|
||||
test("switch component position", async () => {
|
||||
const childInstances = [];
|
||||
class Child extends Component {
|
||||
static template = xml`<div t-esc="props.key"></div>`;
|
||||
setup() {
|
||||
childInstances.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
class Parent extends Component {
|
||||
static components = { Child };
|
||||
static template = xml`<span>
|
||||
<t t-foreach="clist" t-as="c" t-key="c">
|
||||
<Child key="c"/>
|
||||
</t>
|
||||
</span>`;
|
||||
|
||||
clist = [1, 2];
|
||||
}
|
||||
|
||||
const parent = await mount(Parent, fixture);
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>1</div><div>2</div>");
|
||||
parent.clist = [2, 1];
|
||||
await parent.render();
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>2</div><div>1</div>");
|
||||
expect(childInstances.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
import { snapshotEverything, makeTestFixture, addTemplate } from "../helpers";
|
||||
import { Component, mount, xml } from "../../src/index";
|
||||
|
||||
snapshotEverything();
|
||||
|
||||
let fixture: HTMLElement;
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = makeTestFixture();
|
||||
});
|
||||
|
||||
describe("t-key", () => {
|
||||
test("t-key on Component", async () => {
|
||||
let childInstance = null;
|
||||
class Child extends Component {
|
||||
static template = xml`<div t-esc="props.key"></div>`;
|
||||
|
||||
setup() {
|
||||
childInstance = this;
|
||||
}
|
||||
}
|
||||
|
||||
class Parent extends Component {
|
||||
static components = { Child };
|
||||
static template = xml`<span><Child t-key="key" key="key" /></span>`;
|
||||
|
||||
key = 1;
|
||||
}
|
||||
|
||||
const parent = await mount(Parent, fixture);
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>1</div>");
|
||||
|
||||
const oldChild = childInstance;
|
||||
parent.key = 2;
|
||||
await parent.render();
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>2</div>");
|
||||
expect(oldChild === childInstance).toBeFalsy();
|
||||
});
|
||||
|
||||
test("t-key on Component as a function", async () => {
|
||||
let childInstance = null;
|
||||
class Child extends Component {
|
||||
static template = xml`<div t-esc="props.key"></div>`;
|
||||
|
||||
setup() {
|
||||
childInstance = this;
|
||||
}
|
||||
}
|
||||
|
||||
let keyCalls = 0;
|
||||
let __key = 1;
|
||||
class Parent extends Component {
|
||||
static components = { Child };
|
||||
static template = xml`<span><Child t-key="key" key="key" /></span>`;
|
||||
|
||||
get key() {
|
||||
keyCalls++;
|
||||
return __key;
|
||||
}
|
||||
}
|
||||
|
||||
const parent = await mount(Parent, fixture);
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>1</div>");
|
||||
expect(keyCalls).toBe(2); // one for t-key, the other for the props
|
||||
|
||||
const oldChild = childInstance;
|
||||
__key = 2;
|
||||
await parent.render();
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>2</div>");
|
||||
expect(oldChild === childInstance).toBeFalsy();
|
||||
expect(keyCalls).toBe(4);
|
||||
});
|
||||
|
||||
test("t-key on multiple Components", async () => {
|
||||
const childInstances = [];
|
||||
class Child extends Component {
|
||||
static template = xml`<div t-esc="props.key"></div>`;
|
||||
|
||||
setup() {
|
||||
childInstances.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
class Parent extends Component {
|
||||
static components = { Child };
|
||||
static template = xml`<span>
|
||||
<Child t-key="key1" key="key1" />
|
||||
<Child t-key="key2" key="key2" />
|
||||
</span>`;
|
||||
|
||||
key1 = 1;
|
||||
key2 = 2;
|
||||
}
|
||||
|
||||
const parent = await mount(Parent, fixture);
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>1</div><div>2</div>");
|
||||
|
||||
parent.key1 = 2;
|
||||
parent.key2 = 1;
|
||||
await parent.render();
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>2</div><div>1</div>");
|
||||
expect(childInstances.length).toBe(4);
|
||||
});
|
||||
|
||||
test("t-key on multiple Components with t-call 1", async () => {
|
||||
const childInstances = [];
|
||||
class Child extends Component {
|
||||
static template = xml`<div t-esc="props.key"></div>`;
|
||||
|
||||
setup() {
|
||||
childInstances.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
addTemplate("calledTemplate", `<Child t-key="key" key="key" />`);
|
||||
|
||||
class Parent extends Component {
|
||||
static components = { Child };
|
||||
static template = xml`<span>
|
||||
<t t-call="calledTemplate"><t t-set="key" t-value="key1" /></t>
|
||||
<t t-call="calledTemplate"><t t-set="key" t-value="key2" /></t>
|
||||
</span>`;
|
||||
|
||||
key1 = 1;
|
||||
key2 = 2;
|
||||
}
|
||||
|
||||
const parent = await mount(Parent, fixture);
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>1</div><div>2</div>");
|
||||
|
||||
parent.key1 = 2;
|
||||
parent.key2 = 1;
|
||||
await parent.render();
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>2</div><div>1</div>");
|
||||
expect(childInstances.length).toBe(4);
|
||||
});
|
||||
|
||||
test("t-key on multiple Components with t-call 2", async () => {
|
||||
const childInstances = [];
|
||||
class Child extends Component {
|
||||
static template = xml`<div t-esc="props.key"></div>`;
|
||||
|
||||
setup() {
|
||||
childInstances.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
addTemplate(
|
||||
"calledTemplate",
|
||||
`<Child t-key="key1" key="key1" /><Child t-key="key2" key="key2" />`
|
||||
);
|
||||
|
||||
class Parent extends Component {
|
||||
static components = { Child };
|
||||
static template = xml`<span>
|
||||
<t t-call="calledTemplate" />
|
||||
</span>`;
|
||||
|
||||
key1 = 1;
|
||||
key2 = 2;
|
||||
}
|
||||
|
||||
const parent = await mount(Parent, fixture);
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>1</div><div>2</div>");
|
||||
|
||||
parent.key1 = 2;
|
||||
parent.key2 = 1;
|
||||
await parent.render();
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>2</div><div>1</div>");
|
||||
expect(childInstances.length).toBe(4);
|
||||
});
|
||||
|
||||
test("t-foreach with t-key switch component position", async () => {
|
||||
const childInstances = [];
|
||||
class Child extends Component {
|
||||
static template = xml`<div t-esc="props.key"></div>`;
|
||||
setup() {
|
||||
childInstances.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
class Parent extends Component {
|
||||
static components = { Child };
|
||||
static template = xml`<span>
|
||||
<t t-foreach="clist" t-as="c" t-key="c">
|
||||
<Child key="c + key1" t-key="key1"/>
|
||||
</t>
|
||||
</span>`;
|
||||
|
||||
key1 = "key1";
|
||||
clist = [1, 2];
|
||||
}
|
||||
|
||||
const parent = await mount(Parent, fixture);
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>1key1</div><div>2key1</div>");
|
||||
parent.clist = [2, 1];
|
||||
await parent.render();
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>2key1</div><div>1key1</div>");
|
||||
expect(childInstances.length).toBe(2);
|
||||
childInstances.length = 0;
|
||||
|
||||
parent.clist = [1, 2];
|
||||
parent.key1 = "key2";
|
||||
await parent.render();
|
||||
expect((parent.el as HTMLElement).innerHTML).toBe("<div>1key2</div><div>2key2</div>");
|
||||
expect(childInstances.length).toBe(2);
|
||||
});
|
||||
});
|
||||
@@ -405,8 +405,7 @@ describe("Portal", () => {
|
||||
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);
|
||||
});
|
||||
|
||||
|
||||
@@ -479,7 +479,8 @@ exports[`t-foreach throws error if invalid loop expression 1`] = `
|
||||
ctx[\`item\`] = v_block2[i1];
|
||||
ctx[\`item_index\`] = i1;
|
||||
let key1 = ctx['item'];
|
||||
c_block2[i1] = withKey(block3(), key1);
|
||||
const tKey_1 = ctx['item_index'];
|
||||
c_block2[i1] = withKey(block3(), tKey_1 + key1);
|
||||
}
|
||||
let b2 = list(c_block2);
|
||||
return block1([], [b2]);
|
||||
|
||||
@@ -9,8 +9,41 @@ exports[`t-key can use t-key directive on a node 1`] = `
|
||||
let block1 = createBlock(\`<div><block-text-0/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const tKey_1 = ctx['beer'].id;
|
||||
let d1 = ctx['beer'].name;
|
||||
return block1([d1]);
|
||||
return toggler(tKey_1, block1([d1]));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key can use t-key directive on a node 2 1`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-text-0/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const tKey_1 = ctx['beer'].id;
|
||||
let d1 = ctx['beer'].name;
|
||||
return toggler(tKey_1, block1([d1]));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-key can use t-key directive on a node as a function 1`] = `
|
||||
"function anonymous(bdom, helpers
|
||||
) {
|
||||
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||
|
||||
let block1 = createBlock(\`<div><block-text-0/></div>\`);
|
||||
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
const tKey_1 = ctx['getKey'](ctx['beer']);
|
||||
let d1 = ctx['beer'].name;
|
||||
return toggler(tKey_1, block1([d1]));
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
@@ -102,10 +102,11 @@ exports[`t-ref refs in a loop 1`] = `
|
||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||
ctx[\`item\`] = v_block2[i1];
|
||||
let key1 = ctx['item'];
|
||||
const v1 = ctx['item'];
|
||||
let d1 = (el) => refs[\`\${v1}\`] = el;
|
||||
const tKey_1 = ctx['item'];
|
||||
const v2 = ctx['item'];
|
||||
let d1 = (el) => refs[\`\${v2}\`] = el;
|
||||
let d2 = ctx['item'];
|
||||
c_block2[i1] = withKey(block3([d1, d2]), key1);
|
||||
c_block2[i1] = withKey(block3([d1, d2]), tKey_1 + key1);
|
||||
}
|
||||
let b2 = list(c_block2);
|
||||
return block1([], [b2]);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { renderToString, snapshotEverything } from "../helpers";
|
||||
import { renderToString, renderToBdom, snapshotEverything, makeTestFixture } from "../helpers";
|
||||
import { mount, patch } from "../../src/blockdom/index";
|
||||
|
||||
snapshotEverything();
|
||||
|
||||
@@ -10,6 +11,28 @@ describe("t-key", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("can use t-key directive on a node as a function", () => {
|
||||
const template = `<div t-key="getKey(beer)"><t t-esc="beer.name"/></div>`;
|
||||
const getKey = (arg: any) => arg.id;
|
||||
expect(renderToString(template, { getKey, beer: { id: 12, name: "Chimay Rouge" } })).toBe(
|
||||
"<div>Chimay Rouge</div>"
|
||||
);
|
||||
});
|
||||
|
||||
test("can use t-key directive on a node 2", async () => {
|
||||
const template = `<div t-key="beer.id"><t t-esc="beer.name"/></div>`;
|
||||
const bd = renderToBdom(template, { beer: { id: 12, name: "Chimay Rouge" } });
|
||||
const fixture = makeTestFixture();
|
||||
await mount(bd, fixture);
|
||||
const div = fixture.firstChild;
|
||||
|
||||
expect((div as HTMLElement).outerHTML).toBe("<div>Chimay Rouge</div>");
|
||||
const bd2 = renderToBdom(template, { beer: { id: 13, name: "Chimay Rouge" } });
|
||||
await patch(bd, bd2);
|
||||
expect(div !== fixture.firstChild).toBeTruthy();
|
||||
expect((div as HTMLElement).outerHTML).toBe("<div>Chimay Rouge</div>");
|
||||
});
|
||||
|
||||
test("t-key directive in a list", () => {
|
||||
const template = `<ul>
|
||||
<li t-foreach="beers" t-as="beer" t-key="beer.id"><t t-esc="beer.name"/></li>
|
||||
|
||||
Reference in New Issue
Block a user