|
1 | 1 | import { renderHook, act } from '@testing-library/react'; |
2 | 2 | import { useSingleFileInput } from './useSingleFileInput'; |
3 | 3 |
|
4 | | -afterEach(() => { |
5 | | - document.body.innerHTML = ''; |
6 | | -}); |
7 | | - |
8 | 4 | describe('useSingleFileInput', () => { |
| 5 | + afterEach(() => { |
| 6 | + document.body.innerHTML = ''; |
| 7 | + }); |
| 8 | + |
9 | 9 | it('should create an input element and append it to the body', () => { |
10 | 10 | const onSetFile = jest.fn(); |
11 | 11 | renderHook(() => useSingleFileInput(onSetFile)); |
12 | 12 |
|
13 | | - const input = document.createElement('input'); |
14 | | - input.type = 'file'; |
15 | | - input.style.display = 'none'; |
16 | | - document.body.appendChild(input); |
17 | | - expect(input).toBeDefined(); |
18 | | - expect((input as HTMLInputElement).style.display).toBe('none'); |
| 13 | + const inputs = document.querySelectorAll('input[type="file"]'); |
| 14 | + expect(inputs).toHaveLength(1); |
| 15 | + expect((inputs[0] as HTMLInputElement).style.display).toBe('none'); |
19 | 16 | }); |
20 | 17 |
|
21 | 18 | it('should set the accept attribute based on fileType option', () => { |
@@ -68,4 +65,62 @@ describe('useSingleFileInput', () => { |
68 | 65 | const formData = onSetFile.mock.calls[0][1] as FormData; |
69 | 66 | expect(formData.get('test-field')).toBe(file); |
70 | 67 | }); |
| 68 | + |
| 69 | + it('should not call onSetFile when no file is selected', () => { |
| 70 | + const onSetFile = jest.fn(); |
| 71 | + renderHook(() => useSingleFileInput(onSetFile, 'test-field')); |
| 72 | + |
| 73 | + const input = document.querySelector('input[type="file"]') as HTMLInputElement; |
| 74 | + |
| 75 | + Object.defineProperty(input, 'files', { |
| 76 | + value: [], |
| 77 | + }); |
| 78 | + |
| 79 | + act(() => { |
| 80 | + input.dispatchEvent(new Event('change')); |
| 81 | + }); |
| 82 | + |
| 83 | + expect(onSetFile).not.toHaveBeenCalled(); |
| 84 | + }); |
| 85 | + |
| 86 | + it('should remove input element on unmount', () => { |
| 87 | + const onSetFile = jest.fn(); |
| 88 | + const { unmount } = renderHook(() => useSingleFileInput(onSetFile)); |
| 89 | + |
| 90 | + expect(document.querySelectorAll('input[type="file"]')).toHaveLength(1); |
| 91 | + |
| 92 | + unmount(); |
| 93 | + |
| 94 | + expect(document.querySelectorAll('input[type="file"]')).toHaveLength(0); |
| 95 | + }); |
| 96 | + |
| 97 | + it('should reset input value when calling reset', () => { |
| 98 | + const onSetFile = jest.fn(); |
| 99 | + const { result } = renderHook(() => useSingleFileInput(onSetFile)); |
| 100 | + const [, reset] = result.current; |
| 101 | + |
| 102 | + const input = document.querySelector('input[type="file"]') as HTMLInputElement; |
| 103 | + |
| 104 | + const setterSpy = jest.spyOn(input, 'value', 'set'); |
| 105 | + |
| 106 | + act(() => { |
| 107 | + reset(); |
| 108 | + }); |
| 109 | + |
| 110 | + expect(setterSpy).toHaveBeenCalledWith(''); |
| 111 | + }); |
| 112 | + |
| 113 | + it('should update accept attribute when fileType option changes', () => { |
| 114 | + const onSetFile = jest.fn(); |
| 115 | + const { rerender } = renderHook( |
| 116 | + ({ fileType }: { fileType?: string }) => |
| 117 | + useSingleFileInput(onSetFile, 'image', { fileType }), |
| 118 | + { initialProps: { fileType: 'image/*' } } |
| 119 | + ); |
| 120 | + |
| 121 | + rerender({ fileType: 'video/*' }); |
| 122 | + |
| 123 | + const input = document.querySelector('input[type="file"]') as HTMLInputElement; |
| 124 | + expect(input.getAttribute('accept')).toBe('video/*'); |
| 125 | + }); |
71 | 126 | }); |
0 commit comments