import * as React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ComponentClassNames } from '../../shared';
import { DEFAULT_ROW_COUNT, TextAreaField } from '../TextAreaField';
import {
testFlexProps,
expectFlexContainerStyleProps,
} from '../../Flex/__tests__/Flex.test';
import { AUTO_GENERATED_ID_PREFIX } from '../../utils/useStableId';
const label = 'Field';
const testId = 'testId';
describe('TextAreaField component', () => {
describe('wrapper Flex', () => {
it('should render default and custom classname', async () => {
const customClassName = 'my-textareafield';
render(
);
const field = await screen.findByTestId(testId);
expect(field).toHaveClass(customClassName);
expect(field).toHaveClass(ComponentClassNames.Field);
expect(field).toHaveClass(ComponentClassNames.TextAreaField);
});
it('should render all flex style props', async () => {
render(
);
const field = await screen.findByTestId('testId');
expectFlexContainerStyleProps(field);
});
});
describe('Label', () => {
it('should render expected field classname', async () => {
render();
const label = await screen.findByText('Field');
expect(label).toHaveClass(ComponentClassNames.Label);
});
it('should have `amplify-visually-hidden` class when labelHidden is true', async () => {
render();
const label = await screen.findByText('Search');
expect(label).toHaveClass('amplify-visually-hidden');
});
});
describe('TextArea field', () => {
it('should render labeled textarea when id is provided', async () => {
render(
);
const field = await screen.findByLabelText(label);
expect(field.tagName).toBe('TEXTAREA');
expect(field).toHaveClass(ComponentClassNames.Textarea);
expect(field.id).toBe('testField');
});
it('should forward ref to DOM element', async () => {
const ref = React.createRef();
render();
await screen.findByLabelText(label);
expect(ref?.current?.nodeName).toBe('TEXTAREA');
});
it('should render labeled input when id is not provided, and is autogenerated', async () => {
render();
const field = await screen.findByLabelText(label);
expect(field.id.startsWith(AUTO_GENERATED_ID_PREFIX)).toBe(true);
expect(field).toHaveClass(ComponentClassNames.Textarea);
});
it('should render the state attributes', async () => {
render(
);
const field = await screen.findByRole('textbox');
expect(field).toHaveAttribute('disabled', '');
expect(field).toHaveAttribute('readonly', '');
expect(field).toHaveAttribute('required', '');
expect(field).toHaveAttribute('rows', DEFAULT_ROW_COUNT.toString());
});
it('should render the rows attributes', async () => {
const rowCount = 10;
render();
const field = await screen.findByRole('textbox');
expect(field).toHaveAttribute('rows', String(rowCount));
});
it('should set size and variation data attributes', async () => {
render(
);
const textAreaField = await screen.findByTestId('testField');
const textArea = await screen.findByRole('textbox');
expect(textAreaField).toHaveAttribute('data-size', 'small');
expect(textArea).toHaveAttribute('data-variation', 'quiet');
});
it('should render size classes for TextAreaField', async () => {
render(
);
const small = await screen.findByTestId('small');
const large = await screen.findByTestId('large');
expect(small.classList).toContain(
`${ComponentClassNames['Field']}--small`
);
expect(large.classList).toContain(
`${ComponentClassNames['Field']}--large`
);
});
it('can set defaultValue', async () => {
render();
const field = await screen.findByRole('textbox');
expect(field.value).toBe('test');
});
it('show add aria-invalid attribute to textarea when hasError', async () => {
render(
);
const field = await screen.findByRole('textbox');
expect(field).toHaveAttribute('aria-invalid');
});
it('should set resize style property', async () => {
render();
const field = await screen.findByRole('textbox');
expect(field).toHaveStyle('resize: horizontal');
});
it('should fire event handlers', async () => {
const onChange = jest.fn();
const onInput = jest.fn();
const onPaste = jest.fn();
render(
);
const field = await screen.findByRole('textbox');
userEvent.type(field, 'hello');
userEvent.paste(field, 'there');
expect(onChange).toHaveBeenCalled();
expect(onInput).toHaveBeenCalled();
expect(onPaste).toHaveBeenCalled();
});
});
describe('error messages', () => {
const errorMessage = 'This is an error message';
it("don't show when hasError is false", () => {
render(
);
const errorText = screen.queryByText(errorMessage);
expect(errorText).not.toBeInTheDocument();
});
it('show when hasError and errorMessage', () => {
render(
);
const errorText = screen.queryByText(errorMessage);
expect(errorText?.innerHTML).toContain(errorMessage);
});
});
describe('descriptive message', () => {
it('renders when descriptiveText is provided', () => {
render(
);
const descriptiveText = screen.queryByText('Description');
expect(descriptiveText?.innerHTML).toContain('Description');
});
it('should map to descriptive text correctly', async () => {
const descriptiveText = 'Description';
render(
);
const field = await screen.findByRole('textbox');
expect(field).toHaveAccessibleDescription(descriptiveText);
});
});
});