admin/hooks/useAsyncResource.test.ts
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

65 lines
2.0 KiB
TypeScript

import { act, renderHook, waitFor } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import { clearAsyncResourceCache, invalidateAsyncResource, useAsyncResource } from '@/hooks/useAsyncResource'
describe('useAsyncResource', () => {
it('reuses fresh cached data and supports explicit invalidation', async () => {
const key = 'test:cached-resource'
const load = vi.fn().mockResolvedValue({ value: 1 })
const first = renderHook(() => useAsyncResource(load, { cacheKey: key }))
await waitFor(() => {
expect(first.result.current.data).toEqual({ value: 1 })
})
first.unmount()
const second = renderHook(() => useAsyncResource(load, { cacheKey: key }))
await waitFor(() => {
expect(second.result.current.isLoading).toBe(false)
})
expect(load).toHaveBeenCalledTimes(1)
invalidateAsyncResource(key)
await act(async () => {
await second.result.current.refetch()
})
expect(load).toHaveBeenCalledTimes(2)
})
it('clearAsyncResourceCache drops all keys so a later mount refetches', async () => {
const key = 'test:clear-all'
const load = vi.fn().mockResolvedValue({ value: 1 })
const first = renderHook(() => useAsyncResource(load, { cacheKey: key }))
await waitFor(() => {
expect(first.result.current.data).toEqual({ value: 1 })
})
first.unmount()
clearAsyncResourceCache()
const second = renderHook(() => useAsyncResource(load, { cacheKey: key }))
await waitFor(() => {
expect(second.result.current.data).toEqual({ value: 1 })
})
expect(load).toHaveBeenCalledTimes(2)
})
it('aborts an in-flight request on unmount', () => {
let receivedSignal: AbortSignal | undefined
const load = vi.fn((signal: AbortSignal) => {
receivedSignal = signal
return new Promise<never>(() => undefined)
})
const hook = renderHook(() => useAsyncResource(load, { retries: 0 }))
hook.unmount()
expect(receivedSignal?.aborted).toBe(true)
})
})