Skip to content

Commit

Permalink
fix(store): fix standalone computed and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DawidWraga committed May 22, 2024
1 parent 960ba51 commit 25bfb22
Show file tree
Hide file tree
Showing 2 changed files with 237 additions and 20 deletions.
35 changes: 15 additions & 20 deletions packages/store/src/create-computed/create-computed-methods.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable no-unused-vars */

import { Simplify, StoreApi } from '../types';
import { isObject } from '../utils/assertions';

type ComputedDef<TReadValue, TWriteInput = TReadValue, TReadInput = void> =
| {
Expand Down Expand Up @@ -76,18 +77,6 @@ export function createComputedMethods<
const computedProperty = computedProperties[key];
const isFunction = typeof computedProperty === 'function';

// use: () => computedProperties[key](),
// get: () => {
// // @ts-expect-error
// store._replaceUseWithGet = true;

// const result = computedCallback(store)[key]();
// // @ts-expect-error
// store._replaceUseWithGet = false;

// return result;
// },

if (isFunction) {
return [
key,
Expand Down Expand Up @@ -154,18 +143,24 @@ export function computed<TReturnType>(
): ComputedStandalone<TReturnType> {
const result: any = {
get: (...args: any[]) => {
const proxyResult = fn('get');
if (typeof proxyResult === 'function') {
return proxyResult(...args);
const fnReturnValue = fn('get');
const isObjValue = isObject(fnReturnValue);

if (isObjValue && 'get' in fnReturnValue) {
return fnReturnValue.get(...args);
} else {
return fnReturnValue;
}
return proxyResult;
},
use: (...args: any[]) => {
const proxyResult = fn('use');
if (typeof proxyResult === 'function') {
return proxyResult(...args);
const fnReturnValue = fn('use');
const isObjValue = isObject(fnReturnValue);

if (isObjValue && 'get' in fnReturnValue) {
return fnReturnValue.get(...args);
} else {
return fnReturnValue;
}
return proxyResult;
},
};

Expand Down
222 changes: 222 additions & 0 deletions packages/store/test/v2/array-todo-store-with-computed.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
import { describe, expect, test } from 'vitest';
import { computed, store } from '../../src';
type Todo = {
id: number;
text: string;
completed: boolean;
};

const createTodoStore = () => {
const $todos = store<Todo[]>([]);
const $activeTodoId = store<number | null>(null);

const $activeTodo = computed((method) => {
const get = () => {
const todos = $todos[method]();
const activeTodoId = $activeTodoId[method]();
return todos.find((todo) => todo.id === activeTodoId);
};

const set = (todo: Todo) => {
const activeTodo = get();
if (!activeTodo) return;

$todos.set((draft) => {
const todoIndex = draft.findIndex((todo) => todo.id === activeTodo.id);
if (todoIndex !== -1) {
draft[todoIndex] = todo;
}
});
};

return { get, set };
});

function addTodo(todo: Todo) {
$todos.set((draft) => {
draft.push(todo);
});
}

function toggleTodo(id: number) {
$todos.set((draft) => {
const todo = draft.find((todo) => todo.id === id);
if (todo) {
todo.completed = !todo.completed;
}
});
}

function removeTodo(id: number) {
$todos.set((draft) => {
const index = draft.findIndex((todo) => todo.id === id);
if (index !== -1) {
draft.splice(index, 1);
}
});
}

return {
$todos,
addTodo,
toggleTodo,
removeTodo,
$activeTodoId,
$activeTodo,
};
};

describe('todo store', () => {
test('add todo item', () => {
const { $todos, addTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
expect($todos.get()).toStrictEqual([
{ id: 1, text: 'Buy groceries', completed: false },
]);
});

test('add multiple todo items', () => {
const { $todos, addTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
addTodo({ id: 2, text: 'Do laundry', completed: false });
expect($todos.get()).toStrictEqual([
{ id: 1, text: 'Buy groceries', completed: false },
{ id: 2, text: 'Do laundry', completed: false },
]);
});

test('toggle todo item', () => {
const { $todos, addTodo, toggleTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
toggleTodo(1);
expect($todos.get()).toStrictEqual([
{ id: 1, text: 'Buy groceries', completed: true },
]);
});

test('toggle non-existent todo item', () => {
const { $todos, addTodo, toggleTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
toggleTodo(2);
expect($todos.get()).toStrictEqual([
{ id: 1, text: 'Buy groceries', completed: false },
]);
});

test('remove todo item', () => {
const { $todos, addTodo, removeTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
addTodo({ id: 2, text: 'Do laundry', completed: false });
removeTodo(1);
expect($todos.get()).toStrictEqual([
{ id: 2, text: 'Do laundry', completed: false },
]);
});

test('remove non-existent todo item', () => {
const { $todos, addTodo, removeTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
removeTodo(2);
expect($todos.get()).toStrictEqual([
{ id: 1, text: 'Buy groceries', completed: false },
]);
});

test('update todo item text', () => {
const { $todos, addTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
$todos.set((draft) => {
const todo = draft.find((todo) => todo.id === 1);
if (todo) {
todo.text = 'Buy milk';
}
});
expect($todos.get()).toStrictEqual([
{ id: 1, text: 'Buy milk', completed: false },
]);
});

test('clear all todo items', () => {
const { $todos, addTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
addTodo({ id: 2, text: 'Do laundry', completed: false });
$todos.set([]);
expect($todos.get()).toStrictEqual([]);
});

// Add more test cases as needed
});

describe('computed tests', () => {
test('set active todo ID', () => {
const { addTodo, $activeTodoId } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
addTodo({ id: 2, text: 'Do laundry', completed: false });
$activeTodoId.set(1);
expect($activeTodoId.get()).toBe(1);
});

test('get active todo', () => {
const { addTodo, $activeTodoId, $activeTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
addTodo({ id: 2, text: 'Do laundry', completed: false });
$activeTodoId.set(1);
const activeTodo = $activeTodo.get();

expect(activeTodo).toStrictEqual({
id: 1,
text: 'Buy groceries',
completed: false,
});
});

test('get active todo when no active todo ID is set', () => {
const { addTodo, $activeTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
addTodo({ id: 2, text: 'Do laundry', completed: false });
expect($activeTodo.get()).toBeUndefined();
});

test('get active todo when active todo ID does not exist', () => {
const { addTodo, $activeTodoId, $activeTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
addTodo({ id: 2, text: 'Do laundry', completed: false });
$activeTodoId.set(3);
expect($activeTodo.get()).toBeUndefined();
});

test('update active todo', () => {
const { $todos, addTodo, $activeTodoId, $activeTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
addTodo({ id: 2, text: 'Do laundry', completed: false });
$activeTodoId.set(1);
$activeTodo.set({ id: 1, text: 'Buy milk', completed: false });
expect($todos.get()).toStrictEqual([
{ id: 1, text: 'Buy milk', completed: false },
{ id: 2, text: 'Do laundry', completed: false },
]);
});

test('update active todo when no active todo ID is set', () => {
const { $todos, addTodo, $activeTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
addTodo({ id: 2, text: 'Do laundry', completed: false });
$activeTodo.set({ id: 1, text: 'Buy milk', completed: false });
expect($todos.get()).toStrictEqual([
{ id: 1, text: 'Buy groceries', completed: false },
{ id: 2, text: 'Do laundry', completed: false },
]);
});

test('update active todo when active todo ID does not exist', () => {
const { $todos, addTodo, $activeTodoId, $activeTodo } = createTodoStore();
addTodo({ id: 1, text: 'Buy groceries', completed: false });
addTodo({ id: 2, text: 'Do laundry', completed: false });
$activeTodoId.set(3);
$activeTodo.set({ id: 3, text: 'Buy milk', completed: false });
expect($todos.get()).toStrictEqual([
{ id: 1, text: 'Buy groceries', completed: false },
{ id: 2, text: 'Do laundry', completed: false },
]);
});
});

0 comments on commit 25bfb22

Please sign in to comment.