All checks were successful
continuous-integration/drone/push Build is passing
98 lines
3.6 KiB
TypeScript
98 lines
3.6 KiB
TypeScript
import { fireEvent, render, screen } from '@testing-library/react';
|
|
import { createRef } from 'react';
|
|
import { describe, expect, it, vi } from 'vitest';
|
|
import { InputField } from '../../src/components/InputField';
|
|
|
|
describe('InputField', () => {
|
|
it('supports email type and emits change/blur callbacks', () => {
|
|
const onChange = vi.fn();
|
|
const onBlur = vi.fn();
|
|
render(
|
|
<InputField
|
|
label="Email"
|
|
type="email"
|
|
value=""
|
|
onChange={onChange}
|
|
onBlur={onBlur}
|
|
required
|
|
/>,
|
|
);
|
|
|
|
const input = screen.getByLabelText('Email') as HTMLInputElement;
|
|
expect(input.type).toBe('email');
|
|
expect(input).toBeRequired();
|
|
|
|
fireEvent.change(input, { target: { value: 'new@example.com' } });
|
|
fireEvent.blur(input);
|
|
expect(onChange).toHaveBeenCalledTimes(1);
|
|
expect(onBlur).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('passes refs to input element', () => {
|
|
const inputRef = createRef<HTMLInputElement>();
|
|
render(<InputField label="Username" type="text" value="john" onChange={() => {}} inputRef={inputRef} />);
|
|
|
|
expect(inputRef.current).toBeInstanceOf(HTMLInputElement);
|
|
expect(inputRef.current?.value).toBe('john');
|
|
});
|
|
|
|
it('toggles password visibility', () => {
|
|
render(<InputField label="Password" type="password" value="abc" onChange={() => {}} />);
|
|
|
|
expect((screen.getByLabelText('Password') as HTMLInputElement).type).toBe('password');
|
|
fireEvent.click(screen.getByRole('button', { name: 'Show password' }));
|
|
expect((screen.getByLabelText('Password') as HTMLInputElement).type).toBe('text');
|
|
fireEvent.click(screen.getByRole('button', { name: 'Hide password' }));
|
|
expect((screen.getByLabelText('Password') as HTMLInputElement).type).toBe('password');
|
|
});
|
|
|
|
it('renders rightIcon for non-password input and displays errors', () => {
|
|
const { container } = render(
|
|
<InputField
|
|
label="Username"
|
|
type="text"
|
|
value="john"
|
|
onChange={() => {}}
|
|
rightIcon={<span data-testid="right-icon">R</span>}
|
|
error="Invalid username"
|
|
inputClassName="custom-input"
|
|
/>,
|
|
);
|
|
|
|
const input = container.querySelector('input');
|
|
expect(input).toBeInstanceOf(HTMLInputElement);
|
|
expect(input).toHaveClass('pr-10');
|
|
expect(input).toHaveClass('custom-input');
|
|
expect(screen.getByTestId('right-icon')).toBeInTheDocument();
|
|
expect(screen.getByText('Invalid username')).toBeInTheDocument();
|
|
});
|
|
|
|
it('disables password toggle when input is disabled', () => {
|
|
render(
|
|
<InputField
|
|
label="Password"
|
|
type="password"
|
|
value="secret"
|
|
onChange={() => {}}
|
|
disabled
|
|
/>,
|
|
);
|
|
|
|
expect(screen.getByRole('button', { name: 'Show password' })).toBeDisabled();
|
|
});
|
|
|
|
it('supports inline layout classes', () => {
|
|
const { container } = render(
|
|
<InputField label="Username" type="text" value="" onChange={() => {}} layout="inline" />,
|
|
);
|
|
|
|
expect(container.querySelector('label')).toHaveClass('inline-flex');
|
|
expect(container.querySelector('label > div')).not.toHaveClass('mt-1');
|
|
});
|
|
|
|
it('supports rendering without a label', () => {
|
|
const { container } = render(<InputField type="text" value="" onChange={() => {}} />);
|
|
expect(container.querySelector('label > span')).toBeNull();
|
|
});
|
|
});
|