Skip to content

Commit

Permalink
✅ write new tests
Browse files Browse the repository at this point in the history
  • Loading branch information
astoilkov committed Oct 31, 2024
1 parent a6fbad6 commit cd0287f
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 101 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"@types/react-dom": "^18.3.0",
"@vitest/coverage-v8": "^2.0.3",
"@vitest/ui": "^2.0.5",
"jsdom": "^24.1.1",
"fake-indexeddb": "^6.0.0",
"jsdom": "^25.0.1",
"np": "^7.6.3",
"prettier": "^3.3.3",
"react": "^18.3.1",
Expand Down
256 changes: 156 additions & 100 deletions test.ts
Original file line number Diff line number Diff line change
@@ -1,141 +1,197 @@
import "fake-indexeddb/auto";

import { describe, expect, test } from "vitest";
import { act, renderHook } from "@testing-library/react";
import useDb from "./index.js";
import useDb, { type UseDbOptions } from "./index.js";

describe("use-db", () => {
test("defaultValue accepts lazy initializer (like useState)", () => {
const { result } = renderHook(() =>
useDb("todos", {
defaultValue: () => ["first", "second"],
}),
);

const [todos] = result.current;
expect(todos).toStrictEqual(["first", "second"]);
});
describe("optimistic", () => {
test("defaultValue accepts lazy initializer (like useState)", () => {
const key = crypto.randomUUID();
const { result } = renderHook(() =>
useDb(key, {
defaultValue: () => ["first", "second"],
}),
);

test("initial state is written into the state", () => {
const { result } = renderHook(() =>
useDb("todos", { defaultValue: ["first", "second"] }),
);
const [todos] = result.current;
expect(todos).toStrictEqual(["first", "second"]);
});

const [todos] = result.current;
expect(todos).toStrictEqual(["first", "second"]);
});
test("initial state is written into the state", () => {
const key = crypto.randomUUID();
const { result } = renderHook(() =>
useDb(key, {
defaultValue: ["first", "second"],
}),
);

test("updates state", () => {
const { result } = renderHook(() =>
useDb("todos", { defaultValue: ["first", "second"] }),
);
const [todos] = result.current;
expect(todos).toStrictEqual(["first", "second"]);
});

test("updates state", () => {
const key = crypto.randomUUID();
const { result } = renderHook(() =>
useDb(key, {
defaultValue: ["first", "second"],
}),
);

act(() => {
const setTodos = result.current[1];
act(() => {
const setTodos = result.current[1];
setTodos(["third", "forth"]);
});

setTodos(["third", "forth"]);
const [todos] = result.current;
expect(todos).toStrictEqual(["third", "forth"]);
});

const [todos] = result.current;
expect(todos).toStrictEqual(["third", "forth"]);
});
test("updates state with callback function", () => {
const key = crypto.randomUUID();
const { result } = renderHook(() =>
useDb(key, {
defaultValue: ["first", "second"],
}),
);

test("updates state with callback function", () => {
const { result } = renderHook(() =>
useDb("todos", { defaultValue: ["first", "second"] }),
);
act(() => {
const setTodos = result.current[1];

act(() => {
const setTodos = result.current[1];
setTodos((value) => [...value, "third", "forth"]);
});

setTodos((value) => [...value, "third", "forth"]);
const [todos] = result.current;
expect(todos).toStrictEqual(["first", "second", "third", "forth"]);
});

const [todos] = result.current;
expect(todos).toStrictEqual(["first", "second", "third", "forth"]);
});
test("removes item from state", () => {
const key = crypto.randomUUID();
const { result } = renderHook(() =>
useDb(key, {
defaultValue: ["first", "second"],
}),
);

{
act(() => {
const setTodos = result.current[1];
setTodos(["third", "forth"]);
});
const [todos] = result.current;
expect(todos).toStrictEqual(["third", "forth"]);
}

{
act(() => {
const removeItem = result.current[2];
removeItem();
});
const [todos] = result.current;
expect(todos).toStrictEqual(["first", "second"]);
}
});

test("removes item from state", () => {
const { result } = renderHook(() =>
useDb("todos", { defaultValue: ["first", "second"] }),
);
test("persists state across hook re-renders", () => {
const key = crypto.randomUUID();
const { result, rerender } = renderHook(() =>
useDb(key, {
defaultValue: ["first", "second"],
}),
);

{
act(() => {
const setTodos = result.current[1];
setTodos(["third", "forth"]);
setTodos(["third", "fourth"]);
});

rerender();

const [todos] = result.current;
expect(todos).toStrictEqual(["third", "forth"]);
}
expect(todos).toStrictEqual(["third", "fourth"]);
});

test("handles complex objects", () => {
const complexObject = {
nested: { array: [1, 2, 3], value: "test" },
};
const key = crypto.randomUUID();
const { result } = renderHook(() =>
useDb(key, { defaultValue: complexObject }),
);

const [storedObject] = result.current;
expect(storedObject).toEqual(complexObject);

{
act(() => {
const removeItem = result.current[2];
removeItem();
const setObject = result.current[1];
setObject((prev) => ({
...prev,
nested: { ...prev.nested, value: "updated" },
}));
});
const [todos] = result.current;
expect(todos).toStrictEqual(["first", "second"]);
}
});

test("persists state across hook re-renders", () => {
const { result, rerender } = renderHook(() =>
useDb("persistentTodos", { defaultValue: ["first", "second"] }),
);

act(() => {
const setTodos = result.current[1];
setTodos(["third", "fourth"]);
const [updatedObject] = result.current;
expect(updatedObject).toEqual({
nested: { array: [1, 2, 3], value: "updated" },
});
});

rerender();
const key = crypto.randomUUID();
test("handles undefined as a valid state", () => {
const { result } = renderHook(() => useDb(key));

const [todos] = result.current;
expect(todos).toStrictEqual(["third", "fourth"]);
});
const [initialState] = result.current;
expect(initialState).toBeUndefined();

test("handles complex objects", () => {
const complexObject = { nested: { array: [1, 2, 3], value: "test" } };
const { result } = renderHook(() =>
useDb("complexObject", { defaultValue: complexObject }),
);

const [storedObject] = result.current;
expect(storedObject).toEqual(complexObject);

act(() => {
const setObject = result.current[1];
setObject((prev) => ({
...prev,
nested: { ...prev.nested, value: "updated" },
}));
});
act(() => {
const setState = result.current[1];
setState("defined");
});

const [updatedObject] = result.current;
expect(updatedObject).toEqual({
nested: { array: [1, 2, 3], value: "updated" },
const [definedState] = result.current;
expect(definedState).toBe("defined");

act(() => {
const setState = result.current[1];
setState(undefined);
});

const [finalState] = result.current;
expect(finalState).toBeUndefined();
});
});

test("handles undefined as a valid state", () => {
const { result } = renderHook(() => useDb("undefinedState"));
describe("non-optimistic", () => {
test("initial state is written into the state", () => {
const key = crypto.randomUUID();
const { result } = renderHook(() =>
useDb(key, {
optimistic: false,
defaultValue: ["first", "second"],
}),
);

const [initialState] = result.current;
expect(initialState).toBeUndefined();

act(() => {
const setState = result.current[1];
setState("defined");
const [todos] = result.current;
expect(todos).toStrictEqual(["first", "second"]);
});

const [definedState] = result.current;
expect(definedState).toBe("defined");
test("updates state", async () => {
const key = crypto.randomUUID();
const { result } = renderHook(() =>
useDb(key, {
optimistic: false,
defaultValue: ["first", "second"],
}),
);

act(() => {
const setState = result.current[1];
setState(undefined);
});
await act(() => {
const setTodos = result.current[1];
return setTodos(["third", "forth"]);
});

const [finalState] = result.current;
expect(finalState).toBeUndefined();
const [todos] = result.current;
expect(todos).toStrictEqual(["third", "forth"]);
});
});
});

0 comments on commit cd0287f

Please sign in to comment.