diff --git a/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getAddress.test.ts b/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getAddress.test.ts index 4c043f2b..7a2f6f4a 100644 --- a/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getAddress.test.ts +++ b/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getAddress.test.ts @@ -17,7 +17,7 @@ describe('getAddress', () => { it('should return null if domain is null', async () => { const result = await getAddress({ domain: null, connex: mockConnex }); - expect(result).toBeNull(); + expect(result).toBeUndefined(); }); it('should use main resolver for mainnet', async () => { @@ -70,6 +70,6 @@ describe('getAddress', () => { connex: mockConnex, }); - expect(result).toBeNull(); + expect(result).toBeUndefined(); }); }); diff --git a/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getAddress.ts b/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getAddress.ts index a2cfcda7..f4e2c133 100644 --- a/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getAddress.ts +++ b/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getAddress.ts @@ -31,8 +31,8 @@ export const getAddress = async ({ }: { domain: string | null; connex: DAppKitContext['connex']; -}): Promise => { - if (!domain) return null; +}): Promise => { + if (!domain) return undefined; const resolver = connex.thor.genesis.id === genesisBlocks.test.id @@ -48,5 +48,5 @@ export const getAddress = async ({ decoded: { addresses }, } = res; - return (addresses?.[0] as string) || null; + return (addresses?.[0] as string) || undefined; }; diff --git a/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getDomain.test.ts b/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getDomain.test.ts index e2097e66..c073bbdd 100644 --- a/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getDomain.test.ts +++ b/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getDomain.test.ts @@ -17,7 +17,7 @@ describe('getDomain', () => { it('should return null if address is null', async () => { const result = await getDomain({ address: null, connex: mockConnex }); - expect(result).toBeNull(); + expect(result).toBeUndefined(); }); it('should use main resolver for mainnet', async () => { @@ -76,6 +76,6 @@ describe('getDomain', () => { connex: mockConnex, }); - expect(result).toBeNull(); + expect(result).toBeUndefined(); }); }); diff --git a/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getDomain.ts b/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getDomain.ts index d603bada..3528780e 100644 --- a/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getDomain.ts +++ b/packages/dapp-kit-react/src/hooks/useVechainDomain/api/getDomain.ts @@ -29,10 +29,10 @@ export const getDomain = async ({ address, connex, }: { - address: string | null; + address?: string | null; connex: DAppKitContext['connex']; -}): Promise => { - if (!address) return null; +}): Promise => { + if (!address) return undefined; const resolver = connex.thor.genesis.id === genesisBlocks.test.id @@ -48,5 +48,5 @@ export const getDomain = async ({ decoded: { names }, } = res; - return (names?.[0] as string) || null; + return (names?.[0] as string) || undefined; }; diff --git a/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.test.ts b/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.test.ts deleted file mode 100644 index 18fd94c5..00000000 --- a/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.test.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import { renderHook, waitFor } from '@testing-library/react'; -import { useVechainDomain } from './useVechainDomain'; -import { wrapper } from '../../../test/helpers/react-test-helpers'; -import { getDomain } from './api/getDomain'; -import { getAddress } from './api/getAddress'; - -// Mock the useConnex hook -vi.mock('../../hooks/useConnex'); - -vi.mock('./api/getDomain', () => ({ - getDomain: vi.fn(), -})); - -vi.mock('./api/getAddress', () => ({ - getAddress: vi.fn(), -})); - -describe('useVechainDomain', () => { - it('should return null values when addressOrDomain is falsy', () => { - const { result } = renderHook( - () => useVechainDomain({ addressOrDomain: null }), - { wrapper }, - ); - - expect(result.current).toEqual({ - address: null, - domain: null, - isLoading: false, - }); - }); - - it('should fetch domain when given a valid address', async () => { - const mockAddress = '0x1234567890123456789012345678901234567890'; - const mockDomain = 'test.vet'; - - vi.mocked(getDomain).mockResolvedValue(mockDomain); - - const { result } = renderHook( - () => useVechainDomain({ addressOrDomain: mockAddress }), - { wrapper }, - ); - - expect(result.current.isLoading).toBe(true); - - await waitFor(() => { - expect(result.current).toEqual({ - address: mockAddress, - domain: mockDomain, - isLoading: false, - }); - }); - - expect(getDomain).toHaveBeenCalledWith({ - address: mockAddress, - connex: expect.anything(), - }); - }); - - it('should fetch address when given a valid domain', async () => { - const mockAddress = '0x1234567890123456789012345678901234567890'; - const mockDomain = 'test.vet'; - - vi.mocked(getAddress).mockResolvedValue(mockAddress); - - const { result } = renderHook( - () => useVechainDomain({ addressOrDomain: mockDomain }), - { wrapper }, - ); - - expect(result.current.isLoading).toBe(true); - - await waitFor(() => { - expect(result.current).toEqual({ - address: mockAddress, - domain: mockDomain, - isLoading: false, - }); - }); - - expect(getAddress).toHaveBeenCalledWith({ - domain: mockDomain, - connex: expect.anything(), - }); - }); - - it('should handle errors when fetching domain', async () => { - const mockAddress = '0x1234567890123456789012345678901234567890'; - - vi.mocked(getDomain).mockRejectedValue( - new Error('Failed to fetch domain'), - ); - - const { result } = renderHook( - () => useVechainDomain({ addressOrDomain: mockAddress }), - { wrapper }, - ); - - await waitFor(() => { - expect(result.current).toEqual({ - address: mockAddress, - domain: null, - isLoading: false, - }); - }); - }); - - it('should handle errors when fetching address', async () => { - const mockDomain = 'test.vet'; - - vi.mocked(getAddress).mockRejectedValue( - new Error('Failed to fetch address'), - ); - - const { result } = renderHook( - () => useVechainDomain({ addressOrDomain: mockDomain }), - { wrapper }, - ); - - await waitFor(() => { - expect(result.current).toEqual({ - address: null, - domain: null, - isLoading: false, - }); - }); - }); -}); diff --git a/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.test.tsx b/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.test.tsx new file mode 100644 index 00000000..24f5d8bc --- /dev/null +++ b/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.test.tsx @@ -0,0 +1,181 @@ +import { renderHook, waitFor } from '@testing-library/react'; +import { describe, it, expect, vi } from 'vitest'; +import { useVechainDomain } from './useVechainDomain'; +import { wrapper } from '../../../test'; + +vi.mock('./api/getDomain', () => ({ + getDomain: vi.fn().mockImplementation(({ address }) => { + if (address === '0x1234567890123456789012345678901234567890') { + return Promise.resolve('test.vet'); + } + if (address === '0xERROR') { + return Promise.reject(new Error('Network error')); + } + if (address === '0x0000000000000000000000000000000000000000') { + return Promise.reject(new Error('Network error')); + } + return Promise.resolve(null); + }), +})); + +vi.mock('./api/getAddress', () => ({ + getAddress: vi.fn().mockImplementation(({ domain }) => { + if (domain === 'test.vet') { + return Promise.resolve( + '0x1234567890123456789012345678901234567890', + ); + } + if (domain === 'invalid.vet') { + return Promise.resolve( + '0x0000000000000000000000000000000000000000', + ); + } + if (domain === 'error.vet' || domain === '0xERROR') { + return Promise.reject(new Error('Network error')); + } + return Promise.resolve(null); + }), +})); + +describe('useVechainDomain', () => { + it('should return initial state', () => { + const { result } = renderHook( + () => useVechainDomain({ addressOrDomain: null }), + { + wrapper, + }, + ); + + expect(result.current).toEqual({ + address: undefined, + domain: undefined, + isLoading: false, + isValidAddressOrDomain: false, + }); + }); + + it('should handle valid address input', async () => { + const { result } = renderHook( + () => + useVechainDomain({ + addressOrDomain: + '0x1234567890123456789012345678901234567890', + }), + { wrapper }, + ); + + expect(result.current.isLoading).toBe(true); + + await waitFor(() => { + expect(result.current).toEqual({ + address: '0x1234567890123456789012345678901234567890', + domain: 'test.vet', + isLoading: false, + isValidAddressOrDomain: true, + }); + }); + }); + + it('should handle valid domain input', async () => { + const { result } = renderHook( + () => useVechainDomain({ addressOrDomain: 'test.vet' }), + { + wrapper, + }, + ); + + expect(result.current.isLoading).toBe(true); + + await waitFor(() => { + expect(result.current).toEqual({ + address: '0x1234567890123456789012345678901234567890', + domain: 'test.vet', + isLoading: false, + isValidAddressOrDomain: true, + }); + }); + }); + + it('should handle invalid domain input', async () => { + const { result } = renderHook( + () => useVechainDomain({ addressOrDomain: 'invalid.vet' }), + { + wrapper, + }, + ); + + expect(result.current.isLoading).toBe(true); + + await waitFor(() => { + expect(result.current).toEqual({ + address: undefined, + domain: undefined, + isLoading: false, + isValidAddressOrDomain: false, + }); + }); + }); + + it('should handle error when getting domain', async () => { + const { result } = renderHook( + () => useVechainDomain({ addressOrDomain: '0xERROR' }), + { + wrapper, + }, + ); + + expect(result.current.isLoading).toBe(true); + + await waitFor(() => { + expect(result.current).toEqual({ + address: undefined, + domain: undefined, + isLoading: false, + isValidAddressOrDomain: false, + }); + }); + }); + + it('should handle error when getting address', async () => { + const { result } = renderHook( + () => useVechainDomain({ addressOrDomain: 'error.vet' }), + { + wrapper, + }, + ); + + expect(result.current.isLoading).toBe(true); + + await waitFor(() => { + expect(result.current).toEqual({ + address: undefined, + domain: undefined, + isLoading: false, + isValidAddressOrDomain: false, + }); + }); + }); + it('should handle error when getting zero address', async () => { + const { result } = renderHook( + () => + useVechainDomain({ + addressOrDomain: + '0x0000000000000000000000000000000000000000', + }), + { + wrapper, + }, + ); + + expect(result.current.isLoading).toBe(true); + + await waitFor(() => { + expect(result.current).toEqual({ + address: '0x0000000000000000000000000000000000000000', + domain: undefined, + isLoading: false, + isValidAddressOrDomain: true, + }); + }); + }); +}); diff --git a/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.ts b/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.ts index 244ba7ae..0c192dd9 100644 --- a/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.ts +++ b/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.ts @@ -5,9 +5,10 @@ import { getDomain } from './api/getDomain'; import { getAddress } from './api/getAddress'; interface UseVechainDomainReturnType { - address: string | null; - domain: string | null; + address: string | undefined; + domain: string | undefined; isLoading: boolean; + isValidAddressOrDomain: boolean; } /** @@ -20,30 +21,35 @@ export const useVechainDomain = ({ }): UseVechainDomainReturnType => { const connex = useConnex(); - const [address, setAddress] = useState(null); - const [domain, setDomain] = useState(null); + const [address, setAddress] = useState(undefined); + const [domain, setDomain] = useState(undefined); const [isLoading, setIsLoading] = useState(false); + const [isValidAddressOrDomain, setIsValidAddressOrDomain] = useState(false); const isFalsy = !addressOrDomain; const isValidAddress = !isFalsy && addressUtils.isAddress(addressOrDomain); useEffect(() => { if (isFalsy) { - setAddress(null); - setDomain(null); + setAddress(undefined); + setDomain(undefined); setIsLoading(false); + setIsValidAddressOrDomain(false); return; } // if the addressOrDomain is an address, get the domain if (isValidAddress) { setAddress(addressOrDomain); + setIsValidAddressOrDomain(true); setIsLoading(true); getDomain({ address: addressOrDomain, connex }) - .then(setDomain) + .then((domainAddress) => { + setDomain(domainAddress); + }) .catch((err) => { console.error('Error getting domain: ', err); - setDomain(null); + setDomain(undefined); }) .finally(() => { setIsLoading(false); @@ -56,18 +62,29 @@ export const useVechainDomain = ({ setIsLoading(true); getAddress({ domain: addressOrDomain, connex }) .then((domainAddress) => { + if ( + domainAddress === + '0x0000000000000000000000000000000000000000' + ) { + setDomain(undefined); + setAddress(undefined); + setIsValidAddressOrDomain(false); + return; + } setDomain(addressOrDomain); setAddress(domainAddress); + setIsValidAddressOrDomain(true); }) .catch((err) => { console.error('Error getting address: ', err); - setAddress(null); - setDomain(null); + setAddress(undefined); + setDomain(undefined); + setIsValidAddressOrDomain(false); }) .finally(() => { setIsLoading(false); }); }, [addressOrDomain, connex]); - return { address, domain, isLoading }; + return { address, domain, isLoading, isValidAddressOrDomain }; };