From 2dfb4c9c3c1bc5ad00dd78a0a094617a33abda2c Mon Sep 17 00:00:00 2001 From: Diego Borges Date: Tue, 5 Nov 2024 17:21:28 -0300 Subject: [PATCH] Add test coverage around method binding on deep OOP hiearchy --- .../arbor-store/tests/fixtures/Collection.ts | 9 +++++ packages/arbor-store/tests/fixtures/Task.ts | 6 ++++ packages/arbor-store/tests/fixtures/Tasks.ts | 10 ++++++ packages/arbor-store/tests/fixtures/Todo.ts | 6 ++++ packages/arbor-store/tests/fixtures/Todos.ts | 20 +++++++++++ .../arbor-store/tests/scoping/array.test.ts | 34 +++++++++++++++++++ 6 files changed, 85 insertions(+) create mode 100644 packages/arbor-store/tests/fixtures/Collection.ts create mode 100644 packages/arbor-store/tests/fixtures/Task.ts create mode 100644 packages/arbor-store/tests/fixtures/Tasks.ts create mode 100644 packages/arbor-store/tests/fixtures/Todo.ts create mode 100644 packages/arbor-store/tests/fixtures/Todos.ts diff --git a/packages/arbor-store/tests/fixtures/Collection.ts b/packages/arbor-store/tests/fixtures/Collection.ts new file mode 100644 index 00000000..803440fc --- /dev/null +++ b/packages/arbor-store/tests/fixtures/Collection.ts @@ -0,0 +1,9 @@ +import { proxiable } from "../../src/decorators" + +@proxiable +export class Collection extends Array { + push(...items: T[]): number { + // Testing that super is bound to the correct context + return super.push(...items) + } +} diff --git a/packages/arbor-store/tests/fixtures/Task.ts b/packages/arbor-store/tests/fixtures/Task.ts new file mode 100644 index 00000000..cd4e9894 --- /dev/null +++ b/packages/arbor-store/tests/fixtures/Task.ts @@ -0,0 +1,6 @@ +import { proxiable } from "../../src/decorators" + +@proxiable +export class Task { + constructor(public text: string, public done = false) {} +} diff --git a/packages/arbor-store/tests/fixtures/Tasks.ts b/packages/arbor-store/tests/fixtures/Tasks.ts new file mode 100644 index 00000000..20fdc7bb --- /dev/null +++ b/packages/arbor-store/tests/fixtures/Tasks.ts @@ -0,0 +1,10 @@ +import { proxiable } from "../../src/decorators" +import { Collection } from "./Collection" +import { Task } from "./Task" + +@proxiable +export class Tasks extends Collection { + addTask(text: string) { + this.push(new Task(text)) + } +} diff --git a/packages/arbor-store/tests/fixtures/Todo.ts b/packages/arbor-store/tests/fixtures/Todo.ts new file mode 100644 index 00000000..4cdb1cf0 --- /dev/null +++ b/packages/arbor-store/tests/fixtures/Todo.ts @@ -0,0 +1,6 @@ +import { proxiable } from "../../src/decorators" + +@proxiable +export class Todo { + constructor(public text: string, public done = false) {} +} diff --git a/packages/arbor-store/tests/fixtures/Todos.ts b/packages/arbor-store/tests/fixtures/Todos.ts new file mode 100644 index 00000000..0b7ab939 --- /dev/null +++ b/packages/arbor-store/tests/fixtures/Todos.ts @@ -0,0 +1,20 @@ +import { proxiable } from "../../src/decorators" +import { Collection } from "./Collection" +import { Todo } from "./Todo" + +@proxiable +export class Todos extends Collection { + addTodo(text: string) { + this.push(new Todo(text)) + } + + push(...todos: Todo[]): number { + todos.forEach((todo) => { + if (todo.done) { + throw new Error("Todo is already done") + } + }) + + return super.push(...todos) + } +} diff --git a/packages/arbor-store/tests/scoping/array.test.ts b/packages/arbor-store/tests/scoping/array.test.ts index f7b97312..f1145e93 100644 --- a/packages/arbor-store/tests/scoping/array.test.ts +++ b/packages/arbor-store/tests/scoping/array.test.ts @@ -2,6 +2,10 @@ import { describe, expect, it, vi } from "vitest" import { Arbor } from "../../src/arbor" import { ScopedStore } from "../../src/scoping/store" import { detach } from "../../src/utilities" +import { Todo } from "../fixtures/Todo" +import { Todos } from "../fixtures/Todos" +import { Task } from "../fixtures/Task" +import { Tasks } from "../fixtures/Tasks" describe("Array", () => { describe("Symbol.iterator", () => { @@ -404,4 +408,34 @@ describe("Array", () => { expect(store.state).toEqual([]) }) + + describe("method memoization", () => { + it("binds methods to the correct context in the inheritance hiearchy", () => { + const todo1 = new Todo("Do the dishes") + const todo2 = new Todo("Walk the dogs") + const task = new Task("Learn Arbor") + const todos = new Todos(todo1, todo2) + const tasks = new Tasks(task) + + const store = new Arbor({ todos, tasks }) + const scoped = new ScopedStore(store) + + scoped.state.todos.addTodo("Clean the house") + scoped.state.tasks.addTask("Write tests") + + expect(scoped.state.todos.addTodo).toBe(scoped.state.todos.addTodo) + expect(scoped.state.tasks.addTask).toBe(scoped.state.tasks.addTask) + expect(store.state.todos.length).toBe(3) + expect(store.state.tasks.length).toBe(2) + + expect(store.state.todos[0]).toEqual(new Todo("Do the dishes")) + expect(store.state.todos[1]).toEqual(new Todo("Walk the dogs")) + expect(store.state.todos[2]).toEqual(new Todo("Clean the house")) + expect(store.state.todos[3]).toBeUndefined() + + expect(store.state.tasks[0]).toEqual(new Task("Learn Arbor")) + expect(store.state.tasks[1]).toEqual(new Task("Write tests")) + expect(store.state.tasks[2]).toBeUndefined() + }) + }) })