Skip to content

Commit

Permalink
call unmount callbacks on entire Veles app removal (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bloomca authored Jun 9, 2024
1 parent 98b9346 commit 6556fb7
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 5 deletions.
55 changes: 53 additions & 2 deletions integration-tests/attach-component.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { screen } from "@testing-library/dom";

import { attachComponent, createElement } from "../src";
import {
attachComponent,
createElement,
createState,
onUnmount,
Fragment,
} from "../src";

describe("attachComponent", () => {
test("attaches component tree correctly", () => {
attachComponent({
const removeVelesTree = attachComponent({
htmlElement: document.body,
component: createElement("div", {
"data-testid": "attachedComponent",
Expand All @@ -14,5 +20,50 @@ describe("attachComponent", () => {

const docElement = screen.getByTestId("attachedComponent");
expect(docElement).toBeVisible();

removeVelesTree();
});

test("calls all onUnmount callbacks when removing tree", () => {
const appUnmountSpy = jest.fn();
function App() {
onUnmount(appUnmountSpy);

return createElement("div", {
children: [
createElement(Fragment, {
children: [createElement(Child), createElement(Child)],
}),
],
});
}
const state = createState(0);
const childUnmountSpy = jest.fn();
const childSubscriptionSpy = jest.fn();
function Child() {
onUnmount(childUnmountSpy);
state.trackValue(childSubscriptionSpy, { skipFirstCall: true });
return createElement("div", {
children: "test",
});
}
const removeVelesTree = attachComponent({
htmlElement: document.body,
component: createElement("div", {
"data-testid": "attachedComponent",
children: [createElement(App)],
}),
});

state.setValue(1);
expect(childSubscriptionSpy).toHaveBeenCalledTimes(2);

removeVelesTree();
expect(appUnmountSpy).toHaveBeenCalledTimes(1);
expect(childUnmountSpy).toHaveBeenCalledTimes(2);

state.setValue(2);
// subscriptions were removed, so no more calls
expect(childSubscriptionSpy).toHaveBeenCalledTimes(2);
});
});
1 change: 1 addition & 0 deletions src/attach-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ function attachComponent({
// TODO: iterate over every child and call their `onUnmout` method
// and add tests for that
return () => {
wrappedApp._privateMethods._callUnmountHandlers();
velesElementNode.html.remove();
};
}
Expand Down
7 changes: 4 additions & 3 deletions src/create-element/create-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@ function createElement(
// `useAttribute`
let unmountHandlers: Function[] = [];
const callUnmountHandlers = () => {
unmountHandlers.forEach((cb) => cb());
unmountHandlers = [];

// `onUnmount` is logically better to be executed on children first
childComponents.forEach((childComponent) => {
childComponent._privateMethods._callUnmountHandlers();
});

unmountHandlers.forEach((cb) => cb());
unmountHandlers = [];
};

velesNode.html = newElement;
Expand Down

0 comments on commit 6556fb7

Please sign in to comment.