From 57ea46af7a47c5ebf8d8c529080edb093d6b7713 Mon Sep 17 00:00:00 2001 From: fantasticsoul Date: Sun, 26 Nov 2023 01:47:07 +0800 Subject: [PATCH] chore: add test case --- .../__tests__/hooks/useActionLoading.test.ts | 54 +++++++++++++ .../__tests__/hooks/useDerivedAtom.test.tsx | 77 +++++++++++++++++++ .../helux/__tests__/hooks/useService.test.ts | 41 ++++++++++ 3 files changed, 172 insertions(+) create mode 100644 packages/helux/__tests__/hooks/useActionLoading.test.ts create mode 100644 packages/helux/__tests__/hooks/useDerivedAtom.test.tsx create mode 100644 packages/helux/__tests__/hooks/useService.test.ts diff --git a/packages/helux/__tests__/hooks/useActionLoading.test.ts b/packages/helux/__tests__/hooks/useActionLoading.test.ts new file mode 100644 index 00000000..0428f323 --- /dev/null +++ b/packages/helux/__tests__/hooks/useActionLoading.test.ts @@ -0,0 +1,54 @@ +import '@testing-library/jest-dom'; +import { act, renderHook } from '@testing-library/react'; +import { describe, expect, test } from 'vitest'; +import { atom, atomActionAsync, useActionLoading } from '../helux'; +import { delay } from '../util'; + +describe('useDerivedAtom', () => { + async function testLoading(asyncAction, useActionLoading) { + const action1 = asyncAction(async ({ setState }) => { + await delay(100); + setState((draft) => { + draft.val = 100; + }); + }, 'action1'); + + let runCount = 0; + const { result } = renderHook(() => { + runCount += 1; + const [ld] = useActionLoading(); + return ld['action1'].loading; + }); + + expect(runCount).toBe(1); + expect(result.current).toBe(false); + act(() => { + action1(); + }); + expect(runCount).toBe(2); + expect(result.current).toBe(true); // loading + await delay(120); + expect(runCount).toBe(3); + expect(result.current).toBe(false); // loading canceled + } + + test('ctx.asyncAction, ctx.useActionLoading', async () => { + const [, , ctx] = atom(1); + testLoading(ctx.actionAsync, ctx.useActionLoading); + }); + + test('topApi.asyncAction, ctx.useActionLoading', async () => { + const [numAtom, , ctx] = atom(1); + testLoading(atomActionAsync(numAtom), ctx.useActionLoading); + }); + + test('ctx.asyncAction, topApi.useActionLoading', async () => { + const [numAtom, , ctx] = atom(1); + testLoading(ctx.actionAsync, () => useActionLoading(numAtom)); + }); + + test('topApi.asyncAction, topApi.useActionLoading', async () => { + const [numAtom] = atom(1); + testLoading(atomActionAsync(numAtom), () => useActionLoading(numAtom)); + }); +}); diff --git a/packages/helux/__tests__/hooks/useDerivedAtom.test.tsx b/packages/helux/__tests__/hooks/useDerivedAtom.test.tsx new file mode 100644 index 00000000..e0d0352d --- /dev/null +++ b/packages/helux/__tests__/hooks/useDerivedAtom.test.tsx @@ -0,0 +1,77 @@ +import '@testing-library/jest-dom'; +import { act, renderHook } from '@testing-library/react'; +import { describe, expect, test } from 'vitest'; +import { atom, deriveAtom, useDerivedAtom } from '../helux'; +import { delay } from '../util'; + +describe('useDerivedAtom', () => { + test('read and change', async () => { + const [numAtom, setAtom] = atom(1); + const plus1Result = deriveAtom(() => numAtom.val + 1); + + const { result } = renderHook(() => { + const [plus1] = useDerivedAtom(plus1Result); + return plus1; + }); + + expect(result.current).toBe(2); + act(() => { + setAtom(2); + }); + expect(result.current).toBe(3); + }); + + test('read async and change', async () => { + const [numAtom, setAtom] = atom(1); + const plus1Result = deriveAtom({ + fn: () => numAtom.val + 1, + task: async () => { + await delay(100); + return numAtom.val + 100; + }, + }); + + let runCount = 0; + const { result } = renderHook(() => { + runCount += 1; + const [plus1] = useDerivedAtom(plus1Result); + return plus1; + }); + + expect(result.current).toBe(2); + expect(runCount).toBe(1); + act(() => { + setAtom(2); + }); + await delay(120); + expect(result.current).toBe(102); // returned by task + expect(runCount).toBe(3); // loading wil trigger one time render + }); + + test('read async, set showLoading=false', async () => { + const [numAtom, setAtom] = atom(1); + const plus1Result = deriveAtom({ + fn: () => numAtom.val + 1, + task: async () => { + await delay(100); + return numAtom.val + 100; + }, + }); + + let runCount = 0; + const { result } = renderHook(() => { + runCount += 1; + const [plus1] = useDerivedAtom(plus1Result, { showLoading: false }); + return plus1; + }); + + expect(result.current).toBe(2); + expect(runCount).toBe(1); + act(() => { + setAtom(2); + }); + await delay(120); + expect(result.current).toBe(102); // returned by task + expect(runCount).toBe(2); // now only render 2 times + }); +}); diff --git a/packages/helux/__tests__/hooks/useService.test.ts b/packages/helux/__tests__/hooks/useService.test.ts new file mode 100644 index 00000000..8046166b --- /dev/null +++ b/packages/helux/__tests__/hooks/useService.test.ts @@ -0,0 +1,41 @@ +import '@testing-library/jest-dom'; +import { act, renderHook } from '@testing-library/react'; +import { describe, expect, test } from 'vitest'; +import { atom, useAtom, useService } from '../helux'; + +describe('useService', () => { + test('read and change', async () => { + const [numAtom, setAtom] = atom(1); + + let renderCount = 0; + const { result } = renderHook(() => { + renderCount += 1; + useAtom(numAtom); + const srv = useService({ + a() { + return 'stable fn q'; + }, + b() { + return 'stable fn b'; + }, + }); + // srv and its sub methods is stable + return srv; + }); + + expect(renderCount).toBe(1); + const prevSrv = result.current; + const prevFnA = prevSrv.a; + const prevFnB = prevSrv.b; + act(() => { + setAtom(Date.now()); + }); + expect(renderCount).toBe(2); + const currSrv = result.current; + const currFnA = currSrv.a; + const currFnB = currSrv.b; + expect(prevSrv).toBe(currSrv); + expect(prevFnA).toBe(currFnA); + expect(prevFnB).toBe(currFnB); + }); +});