import { act, renderHook } from '@testing-library/react'; import inputmask from '../core/inputmask'; import { beforeEach, describe, expect, it, vi, } from 'vitest'; import useMaskInput from './useMaskInput'; import * as core from '../core'; import type { Input } from '../types'; vi.mock('../core/inputmask', () => ({ default: vi.fn((options) => ({ mask: vi.fn(), options, })), })); vi.mock('../utils/isServer', () => ({ default: false, })); describe('useMaskInput', () => { beforeEach(() => { vi.clearAllMocks(); }); it('returns a ref callback function', () => { const { result } = renderHook(() => useMaskInput({ mask: '999-999' })); expect(typeof result.current).toBe('function'); expect(typeof result.current.unmaskedValue).toBe('function'); }); it('handles null input', () => { const { result } = renderHook(() => useMaskInput({ mask: '999-999' })); act(() => { result.current(null); }); expect(result.current).toBeDefined(); }); it('handles direct input element', () => { const input = document.createElement('input'); vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any); const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' })); act(() => { result.current(input); }); rerender(); expect(inputmask).toHaveBeenCalled(); }); it('exposes the unmasked value from the masked input', () => { const input = document.createElement('input'); vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any); const { result } = renderHook(() => useMaskInput({ mask: '999-999' })); act(() => { result.current(input); }); input.inputmask = { unmaskedvalue: vi.fn(() => '2026-04-01'), } as any; expect(result.current.unmaskedValue()).toBe('2026-04-01'); }); it('handles ref object', () => { const input = document.createElement('input'); const ref = { current: input }; vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any); const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' })); act(() => { result.current(ref as unknown as Input); }); rerender(); expect(inputmask).toHaveBeenCalled(); }); it('handles wrapper element with input inside', () => { const wrapper = document.createElement('div'); const input = document.createElement('input'); wrapper.appendChild(input); vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any); const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' })); act(() => { result.current(wrapper); }); rerender(); expect(inputmask).toHaveBeenCalled(); }); it('handles invalid element in ref', () => { const invalidRef = { current: 'not an element' }; vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any); const { result } = renderHook(() => useMaskInput({ mask: '999-999' })); act(() => { result.current(invalidRef as unknown as Input); }); expect(result.current).toBeDefined(); }); it('handles element that is not HTMLElement in useEffect', () => { vi.spyOn(core, 'isHTMLElement').mockReturnValueOnce(false); const invalidElement = { nodeType: 1 } as unknown as Input; vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any); const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' })); act(() => { result.current(invalidElement as unknown as Input); }); rerender(); expect(result.current).toBeDefined(); }); it('handles wrapper without input inside', () => { const wrapper = document.createElement('div'); vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any); const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' })); act(() => { result.current(wrapper); }); rerender(); expect(inputmask).toHaveBeenCalled(); }); it('works with custom options', () => { const input = document.createElement('input'); vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any); const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999', options: { placeholder: '_' }, })); act(() => { result.current(input); }); rerender(); expect(inputmask).toHaveBeenCalled(); }); it('works with alias masks', () => { const input = document.createElement('input'); vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any); const { result, rerender } = renderHook(() => useMaskInput({ mask: 'cpf' })); act(() => { result.current(input); }); rerender(); expect(inputmask).toHaveBeenCalled(); }); it('calls register callback when provided', () => { const input = document.createElement('input'); const register = vi.fn(); vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any); const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999', register, })); act(() => { result.current(input); }); rerender(); expect(inputmask).toHaveBeenCalled(); }); it('handles textarea element', () => { const textarea = document.createElement('textarea'); vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any); const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' })); act(() => { result.current(textarea); }); rerender(); expect(inputmask).toHaveBeenCalled(); }); it('handles case where findInputElement returns valid element', () => { const wrapper = document.createElement('div'); const input = document.createElement('input'); wrapper.appendChild(input); vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any); const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' })); act(() => { result.current(wrapper); }); rerender(); expect(inputmask).toHaveBeenCalled(); }); });