diff --git a/examples/cypress/component/SimpleTodoList.cy.tsx b/examples/cypress/component/SimpleTodoList.cy.tsx new file mode 100644 index 0000000..9417e17 --- /dev/null +++ b/examples/cypress/component/SimpleTodoList.cy.tsx @@ -0,0 +1,33 @@ +import React from "react" + +import { TodoList, store } from "../../react-todo/store/useTodos" +import SimpleTodoListApp from "../../react-todo/SimpleApp" + +describe("SimpleTodoList", () => { + beforeEach(() => { + store.setState(new TodoList()) + }) + + it("preserves list items references within store upon removal", () => { + cy.mount() + + cy.findByTestId("add-todo-input").type("Clean the house") + cy.findByText("Add").click() + + cy.findByTestId("add-todo-input").type("Walk the dogs") + cy.findByText("Add") + .click() + .then(() => { + const todo1 = store.state[0] + const todo2 = store.state[1] + + cy.findByTestId(`todo-${todo1.id}`).within(() => { + cy.findByText("Delete").click() + }) + + cy.findByTestId(`todo-${todo2.id}`).within(() => { + cy.findByText("Delete").click() + }) + }) + }) +}) diff --git a/examples/cypress/component/TodoList.cy.tsx b/examples/cypress/component/TodoList.cy.tsx index 5f71e37..c57ca69 100644 --- a/examples/cypress/component/TodoList.cy.tsx +++ b/examples/cypress/component/TodoList.cy.tsx @@ -79,4 +79,29 @@ describe("TodoList", () => { cy.findByText("0 of 1 completed").should("exist") }) }) + + it("preserves list items references within store upon removal", () => { + cy.mount() + + cy.findByTestId("add-todo-input").type("Clean the house") + cy.findByText("Add").click() + + cy.findByTestId("add-todo-input").type("Walk the dogs") + cy.findByText("Add").click() + + cy.findByText("All") + .click() + .then(() => { + const todo1 = store.state[0] + const todo2 = store.state[1] + + cy.findByTestId(`todo-${todo1.id}`).within(() => { + cy.findByText("Delete").click() + }) + + cy.findByTestId(`todo-${todo2.id}`).within(() => { + cy.findByText("Delete").click() + }) + }) + }) }) diff --git a/examples/react-todo/SimpleApp.tsx b/examples/react-todo/SimpleApp.tsx new file mode 100644 index 0000000..5d4bdfd --- /dev/null +++ b/examples/react-todo/SimpleApp.tsx @@ -0,0 +1,24 @@ +import React from "react" + +import Summary from "./components/Summary" +import NewTodoForm from "./components/NewTodoForm" +import SimpleTodoList from "./components/SimpleTodoList" + +import "./index.css" + +export default function SimpleApp() { + return ( +
+

todos

+ +
+ + + +
+ +
+
+
+ ) +} diff --git a/examples/react-todo/components/SimpleTodoList.tsx b/examples/react-todo/components/SimpleTodoList.tsx new file mode 100644 index 0000000..e79de57 --- /dev/null +++ b/examples/react-todo/components/SimpleTodoList.tsx @@ -0,0 +1,17 @@ +import React, { memo } from "react" +import { useArbor } from "@arborjs/react" + +import { TodoList, store } from "../store/useTodos" +import TodoView from "./TodoView" + +export default memo(function SimpleTodoList() { + const todos = useArbor(store) as TodoList + + return ( +
+ {todos.map((todo) => ( + + ))} +
+ ) +}) diff --git a/examples/react-todo/components/TodoView.tsx b/examples/react-todo/components/TodoView.tsx index 53be51a..9303351 100644 --- a/examples/react-todo/components/TodoView.tsx +++ b/examples/react-todo/components/TodoView.tsx @@ -10,7 +10,7 @@ export interface TodoProps { export default memo(function TodoView({ id }: TodoProps) { const [editing, setEditing] = useState(false) - const todo = useArbor(store.state.find(t => t.uuid === id)!) + const todo = useArbor(store.state.find((t) => t.uuid === id)!) return (
{ describe("Symbol.iterator", () => { @@ -389,4 +390,18 @@ describe("Array", () => { expect(subscriber).toHaveBeenCalledTimes(2) }) }) + + it("preserves tree links when deleting items via detach", () => { + const state = [{ id: 1 }, { id: 2 }] + + const store = new Arbor(state) + const scoped = new ScopedStore(store) + const item1 = scoped.state[0] + const item2 = scoped.state[1] + + detach(item1) + detach(item2) + + expect(store.state).toEqual([]) + }) })