import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import styles from '@patternfly/react-styles/css/components/TextInputGroup/text-input-group';
import { TextInputGroupMain } from '../TextInputGroupMain';
import { TextInputGroupContext } from '../TextInputGroup';
import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
describe('TextInputGroupMain', () => {
it('renders without children', () => {
render();
expect(screen.getByTestId('TextInputGroupMain')).toBeVisible();
});
it('renders children', () => {
render(Test);
expect(screen.getByText('Test')).toBeVisible();
});
it(`renders with class ${styles.textInputGroupMain}`, () => {
render(Test);
const inputGroupMain = screen.getByText('Test');
expect(inputGroupMain).toHaveClass(styles.textInputGroupMain);
});
it('does not render with class pf-m-icon when an icon prop is not passed', () => {
render(Test);
const inputGroupMain = screen.getByText('Test');
expect(inputGroupMain).not.toHaveClass('pf-m-icon');
});
it('renders with class pf-m-icon when an icon prop is passed', () => {
render(Test);
const inputGroupMain = screen.getByText('Test');
expect(inputGroupMain).toHaveClass('pf-m-icon');
});
it('renders with custom class names provided via prop', () => {
render(Test);
const inputGroupMain = screen.getByText('Test');
expect(inputGroupMain).toHaveClass('custom-class');
});
it(`renders with class ${styles.textInputGroupText} on the inputs parent`, () => {
render(Test);
const inputGroupText = screen.getByRole('textbox').parentNode;
expect(inputGroupText).toHaveClass(styles.textInputGroupText);
});
it(`renders the input with class ${styles.textInputGroupTextInput}`, () => {
render(Test);
const input = screen.getByRole('textbox');
expect(input).toHaveClass(styles.textInputGroupTextInput);
});
it('does not render the icon when it is not passed', () => {
render();
const icon = screen.queryByRole('img', { hidden: true });
expect(icon).not.toBeInTheDocument();
});
it('renders the icon when passed', () => {
render(} />);
const icon = screen.getByRole('img', { hidden: true });
expect(icon).toBeInTheDocument();
});
it('renders the icon as aria hidden', () => {
render(} />);
const icon = screen.getByRole('img', { hidden: true });
expect(icon).toHaveAttribute('aria-hidden', 'true');
});
it('passes the aria-label prop to the input', () => {
render(Test);
const input = screen.getByRole('textbox');
expect(input).toHaveAccessibleName('Test label');
});
it('passes the value prop to the input', () => {
render(Test);
const inputValue = screen.getByDisplayValue('value text');
expect(inputValue).toBeVisible();
});
it('passes the inputId prop to the input', () => {
render(Test);
const input = screen.getByRole('textbox');
expect(input).toHaveAttribute('id', 'input-id');
});
it('passes the placeholder prop to the input', () => {
render(Test);
const inputPlaceholder = screen.getByPlaceholderText('placeholder text');
expect(inputPlaceholder).toBeVisible();
});
it('defaults to an input type of text', () => {
render(Test);
const input = screen.getByRole('textbox');
expect(input).toHaveAttribute('type', 'text');
});
it('updates the input type when a different type is passed', () => {
render(Test);
const textInput = screen.queryByRole('textbox');
const searchInput = screen.getByRole('searchbox');
expect(textInput).not.toBeInTheDocument();
expect(searchInput).toBeVisible();
});
it('does not disable the input when TextInputGroupContext isDisabled is false', () => {
render(
);
const input = screen.getByRole('textbox');
expect(input).not.toBeDisabled();
});
it('disables the input when TextInputGroupContext isDisabled is true', () => {
render(
);
const input = screen.getByRole('textbox');
expect(input).toBeDisabled();
});
it("doesn't render the hint input when a hint prop isn't passed", () => {
// we set the type of the main input to search here so that we can accurately target the hint input
render(Test);
const hintInput = screen.queryByRole('textbox', { hidden: true });
expect(hintInput).not.toBeInTheDocument();
});
it('renders the hint input when a hint prop is passed', () => {
// we set the type of the main input to search here so that we can accurately target the hint input
render(
Test
);
const hintInput = screen.getByRole('textbox', { hidden: true });
expect(hintInput).toBeInTheDocument();
});
it(`renders the hint input with classes ${styles.textInputGroupTextInput} and ${styles.modifiers.hint}`, () => {
// we set the type of the main input to search here so that we can accurately target the hint input
render(
Test
);
const hintInput = screen.getByRole('textbox', { hidden: true });
expect(hintInput).toHaveClass(styles.modifiers.hint);
expect(hintInput).toHaveClass(styles.textInputGroupTextInput);
});
it('renders the hint input as disabled', () => {
// we set the type of the main input to search here so that we can accurately target the hint input
render(
Test
);
const hintInput = screen.getByRole('textbox', { hidden: true });
expect(hintInput).toBeDisabled();
});
it('renders the hint input as aria-hidden', () => {
// we set the type of the main input to search here so that we can accurately target the hint input
render(
Test
);
const hintInput = screen.getByRole('textbox', { hidden: true });
expect(hintInput).toHaveAttribute('aria-hidden', 'true');
});
it('passes the hint prop to the hint input as its value', () => {
// we set the type of the main input to search here so that we can accurately target the hint input
render(
Test
);
const hintInput = screen.getByDisplayValue('value text');
expect(hintInput).toBeVisible();
});
it(`Renders status icon with class ${styles.modifiers.status} when a validated prop is passed`, () => {
render(
);
expect(screen.getByRole('textbox').nextElementSibling).toHaveClass(styles.modifiers.status);
});
it('does not render a status icon when validated is default', () => {
render(
);
expect(screen.queryByRole('textbox').nextElementSibling).toBeNull();
});
it('does not call onChange callback when the input does not change', () => {
const onChangeMock = jest.fn();
render(Test);
expect(onChangeMock).not.toHaveBeenCalled();
});
it('calls the onChange callback when the input changes', async () => {
const onChangeMock = jest.fn();
const user = userEvent.setup();
render(Test);
const input = screen.getByRole('textbox');
await user.type(input, 'Test');
expect(onChangeMock).toHaveBeenCalledTimes(4);
});
it('does not call onFocus callback when the input does not get focus', () => {
const onFocusMock = jest.fn();
render(Test);
expect(onFocusMock).not.toHaveBeenCalled();
});
it('calls the onFocus callback when the input is focused', async () => {
const onFocusMock = jest.fn();
const user = userEvent.setup();
render(Test);
const input = screen.getByRole('textbox');
await user.click(input);
expect(onFocusMock).toHaveBeenCalledTimes(1);
});
it('does not call onBlur callback when the input does not lose focus', async () => {
const onBlurMock = jest.fn();
const user = userEvent.setup();
render(Test);
const input = screen.getByRole('textbox');
await user.click(input);
expect(onBlurMock).not.toHaveBeenCalled();
});
it('calls the onBlur callback when the input loses focus', async () => {
const onBlurMock = jest.fn();
const user = userEvent.setup();
render(Test);
const input = screen.getByRole('textbox');
await user.click(input);
await user.click(document.body);
expect(onBlurMock).toHaveBeenCalledTimes(1);
});
test('Additional props are spread when inputProps prop is passed', () => {
render();
expect(screen.getByLabelText('Test input')).toHaveAttribute('autofocus', 'true');
});
it('matches the snapshot', () => {
const { asFragment } = render(Test);
expect(asFragment()).toMatchSnapshot();
});
});