import { render, screen } from '@testing-library/react'; import '@testing-library/jest-dom'; import userEvent from '@testing-library/user-event'; import { AttachButton } from './AttachButton'; describe('Attach button', () => { it('should render button correctly', () => { render(); expect(screen.getByRole('button', { name: 'Attach' })).toBeTruthy(); }); it('should handle isDisabled prop', () => { render(); expect(screen.getByRole('button', { name: 'Attach' })).toBeDisabled(); }); it('should handle spread props, including aria-label', () => { render(); expect(screen.getByRole('button', { name: 'test' })); }); it('should handle onClick', async () => { const spy = jest.fn(); render(); await userEvent.click(screen.getByRole('button', { name: 'Attach' })); expect(screen.getByRole('tooltip', { name: 'Attach' })).toBeTruthy(); expect(spy).toHaveBeenCalledTimes(1); }); it('should handle className prop', () => { render(); expect(screen.getByRole('button', { name: 'Attach' })).toHaveClass('test'); }); it('should handle custom tooltip correctly', async () => { render(); await userEvent.click(screen.getByRole('button', { name: 'Attach' })); expect(screen.getByRole('tooltip', { name: 'Test' })).toBeTruthy(); }); it('should handle tooltipProps prop', async () => { render(); await userEvent.click(screen.getByRole('button', { name: 'Attach' })); expect(screen.getByRole('tooltip', { name: 'Attach' })).toHaveAttribute('id', 'test'); }); // Based on this because I had no idea how to do this and was looking around: https://stackoverflow.com/a/75562651 // See also https://developer.mozilla.org/en-US/docs/Web/API/File/File for what that file variable is doing it('should handle onAttachAccepted prop', async () => { const spy = jest.fn(); render(); await userEvent.click(screen.getByRole('button', { name: 'Attach' })); const file = new File(['test'], 'test.json'); const input = screen.getByTestId('input') as HTMLInputElement; await userEvent.upload(input, file); expect(input.files).toHaveLength(1); expect(spy).toHaveBeenCalledTimes(1); }); it('should handle isCompact', () => { render(); expect(screen.getByTestId('button')).toHaveClass('pf-m-compact'); }); it('should set correct accept attribute on file input', async () => { render(); await userEvent.click(screen.getByRole('button', { name: 'Attach' })); const input = screen.getByTestId('input') as HTMLInputElement; expect(input).toHaveAttribute('accept', 'text/plain,.txt'); }); it('should call onAttachAccepted when file type is accepted', async () => { const onAttachAccepted = jest.fn(); render( ); const file = new File(['hello'], 'example.txt', { type: 'text/plain' }); const input = screen.getByTestId('input'); await userEvent.upload(input, file); expect(onAttachAccepted).toHaveBeenCalled(); const [attachedFile] = onAttachAccepted.mock.calls[0][0]; expect(attachedFile).toEqual(file); }); it('should not call onAttachAccepted when file type is not accepted', async () => { const onAttachAccepted = jest.fn(); render( ); const file = new File(['[]'], 'example.json', { type: 'application/json' }); const input = screen.getByTestId('input'); await userEvent.upload(input, file); expect(onAttachAccepted).not.toHaveBeenCalled(); }); it('should respect minSize restriction', async () => { const onAttachRejected = jest.fn(); render(); const file = new File(['Test'], 'example.txt', { type: 'text/plain' }); const input = screen.getByTestId('input'); await userEvent.upload(input, file); expect(onAttachRejected).toHaveBeenCalled(); }); it('should respect maxSize restriction', async () => { const onAttachRejected = jest.fn(); render(); const largeContent = 'x'.repeat(200); const file = new File([largeContent], 'example.txt', { type: 'text/plain' }); const input = screen.getByTestId('input'); await userEvent.upload(input, file); expect(onAttachRejected).toHaveBeenCalled(); }); it('should respect maxFiles restriction', async () => { const onAttachRejected = jest.fn(); render(); const files = [ new File(['Test1'], 'example1.txt', { type: 'text/plain' }), new File(['Test2'], 'example2.txt', { type: 'text/plain' }) ]; const input = screen.getByTestId('input'); await userEvent.upload(input, files); expect(onAttachRejected).toHaveBeenCalled(); }); it('should be disabled when isAttachmentDisabled is true', async () => { const onFileDrop = jest.fn(); render(); const file = new File(['Test'], 'example.text', { type: 'text/plain' }); const input = screen.getByTestId('input'); await userEvent.upload(input, file); expect(onFileDrop).not.toHaveBeenCalled(); }); it('should call onAttach when files are attached', async () => { const onAttach = jest.fn(); render(); const file = new File(['Test'], 'example.txt', { type: 'text/plain' }); const input = screen.getByTestId('input'); await userEvent.upload(input, file); expect(onAttach).toHaveBeenCalled(); }); it('should use custom validator when provided', async () => { const validator = jest.fn().mockReturnValue({ message: 'Custom error' }); const onAttachRejected = jest.fn(); render(); const file = new File(['Test'], 'example.txt', { type: 'text/plain' }); const input = screen.getByTestId('input'); await userEvent.upload(input, file); expect(validator).toHaveBeenCalledWith(file); expect(onAttachRejected).toHaveBeenCalled(); }); it('should handle icon prop', () => { render(} />); expect(screen.getByRole('img')).toBeVisible(); }); });