Skip to content

Commit

Permalink
test(core,react): errors & useAsyncAction hook (#462)
Browse files Browse the repository at this point in the history
  • Loading branch information
tien authored Feb 10, 2025
1 parent 6d1501b commit df97995
Show file tree
Hide file tree
Showing 5 changed files with 539 additions and 7 deletions.
37 changes: 37 additions & 0 deletions packages/core/src/errors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ReactiveDotError, QueryError, MutationError } from "./errors.js";
import { describe, it, expect } from "vitest";

describe("ReactiveDotError", () => {
it("should create error with message", () => {
const error = new ReactiveDotError("test error");

expect(error.message).toBe("test error");
expect(error).toBeInstanceOf(Error);
});

it("should create error from another error", () => {
const originalError = new Error("original error");
const error = ReactiveDotError.from(originalError, "wrapped error");

expect(error.message).toBe("wrapped error");
expect(error.cause).toBe(originalError);
});
});

describe("QueryError", () => {
it("should extend ReactiveDotError", () => {
const error = new QueryError("query error");

expect(error).toBeInstanceOf(ReactiveDotError);
expect(error.message).toBe("query error");
});
});

describe("MutationError", () => {
it("should extend ReactiveDotError", () => {
const error = new MutationError("mutation error");

expect(error).toBeInstanceOf(ReactiveDotError);
expect(error.message).toBe("mutation error");
});
});
9 changes: 7 additions & 2 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,25 @@
"scripts": {
"dev": "tsc --build --watch",
"build": "rm -rf build && tsc --build",
"lint": "eslint src"
"lint": "eslint src",
"test": "vitest"
},
"dependencies": {
"@reactive-dot/core": "workspace:^",
"jotai": "^2.11.2"
},
"devDependencies": {
"@reactive-dot/eslint-config": "workspace:^",
"@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.2.0",
"@tsconfig/recommended": "^1.0.8",
"@tsconfig/strictest": "^2.0.5",
"@types/react": "^19.0.8",
"eslint": "^9.20.0",
"jsdom": "^26.0.0",
"react": "^19.0.0",
"typescript": "^5.7.3"
"typescript": "^5.7.3",
"vitest": "^3.0.5"
},
"peerDependencies": {
"react": "18.x || 19.x"
Expand Down
93 changes: 93 additions & 0 deletions packages/react/src/hooks/use-async-action.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { useAsyncAction } from "./use-async-action.js";
import { idle, MutationError, pending } from "@reactive-dot/core";
import { act, renderHook } from "@testing-library/react";
import { Subject } from "rxjs";
import { expect, it, vi } from "vitest";

it("should handle Promise-based actions", async () => {
const mockAction = vi.fn().mockResolvedValue("success");
const { result } = renderHook(() => useAsyncAction(mockAction));

expect(result.current[0]).toBe(idle);

await act(async () => {
result.current[1]();
});

expect(mockAction).toHaveBeenCalled();
expect(result.current[0]).toBe("success");
});

it("should handle Observable-based actions", async () => {
const subject = new Subject<string>();
const mockAction = vi.fn().mockReturnValue(subject);
const { result } = renderHook(() => useAsyncAction(mockAction));

expect(result.current[0]).toBe(idle);

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

expect(result.current[0]).toBe(pending);

act(() => {
subject.next("success");
});

expect(result.current[0]).toBe("success");
});

it("should handle synchronous rejection", async () => {
const error = new Error("test error");
const mockAction = vi.fn(() => {
throw error;
});
const { result } = renderHook(() => useAsyncAction(mockAction));

await act(async () => {
try {
await result.current[1]();
} catch {
/* empty */
}
});

expect(result.current[0]).toBeInstanceOf(MutationError);
expect((result.current[0] as MutationError).cause).toBe(error);
});

it("should handle Promise rejection", async () => {
const error = new Error("test error");
const mockAction = vi.fn().mockRejectedValue(error);
const { result } = renderHook(() => useAsyncAction(mockAction));

await act(async () => {
try {
await result.current[1]();
} catch {
/* empty */
}
});

expect(result.current[0]).toBeInstanceOf(MutationError);
expect((result.current[0] as MutationError).cause).toBe(error);
});

it("should handle Observable errors", async () => {
const subject = new Subject<string>();
const error = new Error("test error");
const mockAction = vi.fn().mockReturnValue(subject);
const { result } = renderHook(() => useAsyncAction(mockAction));

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

act(() => {
subject.error(error);
});

expect(result.current[0]).toBeInstanceOf(MutationError);
expect((result.current[0] as MutationError).cause).toBe(error);
});
5 changes: 5 additions & 0 deletions packages/react/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { defineProject } from "vitest/config";

export default defineProject({
test: { environment: "jsdom" },
});
Loading

0 comments on commit df97995

Please sign in to comment.