[FIX] fiber, lifecycle: trigger a render during the fiber.complete

Have a component which does a render in its onWillPatch, onPatched, onMounted hooks.

Before this commit, the result was incorrect: the second rendering was not taken into account.

After this commit, those renderings are correctly applied at the price of a delayed render when the fiber
is in a critical state.
This commit is contained in:
Lucas Perais (lpe)
2021-12-14 09:31:25 +01:00
committed by Aaron Bohy
parent e2819323ee
commit ddc358f48a
6 changed files with 224 additions and 8 deletions
+117
View File
@@ -1079,4 +1079,121 @@ describe("lifecycle hooks", () => {
"Parent:patched",
]).toBeLogged();
});
test("render in mounted", async () => {
class Parent extends Component {
static template = xml`<span t-esc="patched"/>`;
patched: any;
setup() {
useLogLifecycle();
onMounted(() => {
this.patched = "Patched";
this.render();
});
}
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("<span></span>");
expect([
"Parent:setup",
"Parent:willStart",
"Parent:willRender",
"Parent:rendered",
"Parent:mounted",
"Parent:willRender",
"Parent:rendered",
]).toBeLogged();
await nextTick();
expect(fixture.innerHTML).toBe("<span>Patched</span>");
expect(["Parent:willPatch", "Parent:patched"]).toBeLogged();
});
test("render in patched", async () => {
class Parent extends Component {
static template = xml`<span t-esc="patched"/>`;
patched: any;
setup() {
useLogLifecycle();
onPatched(() => {
if (this.patched === "Patched") {
return;
}
this.patched = "Patched";
this.render();
});
}
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("<span></span>");
expect([
"Parent:setup",
"Parent:willStart",
"Parent:willRender",
"Parent:rendered",
"Parent:mounted",
]).toBeLogged();
parent.render();
await nextTick();
expect(fixture.innerHTML).toBe("<span></span>");
expect([
"Parent:willRender",
"Parent:rendered",
"Parent:willPatch",
"Parent:patched",
"Parent:willRender",
"Parent:rendered",
]).toBeLogged();
await nextTick();
expect(fixture.innerHTML).toBe("<span>Patched</span>");
expect(["Parent:willPatch", "Parent:patched"]).toBeLogged();
});
test("render in willPatch", async () => {
class Parent extends Component {
static template = xml`<span t-esc="patched"/>`;
patched: any;
setup() {
useLogLifecycle();
onWillPatch(() => {
if (this.patched === "Patched") {
return;
}
this.patched = "Patched";
this.render();
});
}
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("<span></span>");
expect([
"Parent:setup",
"Parent:willStart",
"Parent:willRender",
"Parent:rendered",
"Parent:mounted",
]).toBeLogged();
parent.render();
await nextTick();
expect(fixture.innerHTML).toBe("<span></span>");
expect([
"Parent:willRender",
"Parent:rendered",
"Parent:willPatch",
"Parent:patched",
"Parent:willRender",
"Parent:rendered",
]).toBeLogged();
await nextTick();
expect(["Parent:willPatch", "Parent:patched"]).toBeLogged();
expect(fixture.innerHTML).toBe("<span>Patched</span>");
});
});