import * as React from 'react';
import { render, screen } from '@testing-library/react';
import kebabCase from 'lodash/kebabCase';
import { AUTO_GENERATED_ID_PREFIX } from '../../utils/useStableId';
import { ComponentClassNames } from '../../shared';
import { ComponentPropsToStylePropsMap } from '../../types';
import { SwitchField } from '../SwitchField';
describe('Switch Field', () => {
const label = 'My switch label';
describe('Switch wrapper', () => {
it('should pass through the className', () => {
const { container } = render(
);
const wrapper = container.getElementsByClassName(
ComponentClassNames.SwitchField
)[0];
expect(wrapper).toHaveClass('my-switch');
});
it('should render the position classes on SwitchField', () => {
const { container } = render(
);
const wrapper = container.getElementsByClassName(
ComponentClassNames.SwitchWrapper
)[0];
expect(wrapper).toHaveClass(`${ComponentClassNames.SwitchWrapper}--top`);
});
it('should forward ref to DOM element', async () => {
const ref = React.createRef();
render();
await screen.findByLabelText(label);
expect(ref.current?.nodeName).toBe('DIV');
});
it('should set the data-size attribute', () => {
const { container } = render();
const wrapper = container.getElementsByClassName(
ComponentClassNames.SwitchField
)[0] as HTMLElement;
expect(wrapper.dataset['size']).toEqual('large');
});
it('should set the label for attribute to match the passed in id', () => {
const { container } = render(
);
const wrapper = container.getElementsByClassName(
ComponentClassNames.SwitchWrapper
)[0];
expect(wrapper).toHaveAttribute('for', 'my-switch');
});
it('should set the data-label-position attribute', () => {
const { container } = render(
);
const wrapper = container.getElementsByClassName(
ComponentClassNames.SwitchField
)[0] as HTMLElement;
expect(wrapper).toHaveAttribute('data-label-position', 'end');
});
});
describe('Label', () => {
it('should render the passed in label string', () => {
const { container } = render();
const field = container.getElementsByClassName(
ComponentClassNames.SwitchLabel
)[0];
expect(field).toHaveTextContent(label);
});
it('should render the passed in label element', () => {
const label = Element Label;
const { container } = render();
const field = container.getElementsByClassName('my-custom-label')[0];
expect(field).toHaveTextContent('Element Label');
});
it('should hide the label using the visually hidden component when the isLabelHidden flag is passed in', () => {
const { container } = render();
const field = container.getElementsByClassName(
ComponentClassNames.SwitchLabel
)[0];
expect(field).toHaveClass('amplify-visually-hidden');
});
});
describe('Input', () => {
it('should create a checkbox input element', () => {
const { container } = render();
const field = container.getElementsByTagName('input')[0];
expect(field).toHaveAttribute('type', 'checkbox');
});
it('should hide the input with the visually hidden component', () => {
const { container } = render();
const field = container.getElementsByTagName('input')[0].parentElement;
expect(field).toHaveClass('amplify-visually-hidden');
});
it('should pass through the name and value properties to the checkbox', () => {
const { container } = render(
);
const field = container.getElementsByTagName('input')[0];
expect(field).toHaveAttribute('name', 'myCheckbox');
expect(field).toHaveAttribute('value', 'checkboxValue');
});
it('should disable the checkbox with the isDisabled prop', () => {
const { container } = render();
const field = container.getElementsByTagName('input')[0];
expect(field).toHaveProperty('disabled', true);
});
it('should set the input to checked with the isChecked prop', () => {
const { container } = render();
const field = container.getElementsByTagName('input')[0];
expect(field).toBeChecked();
});
it('should update the checked value when a controlled value is updated', async () => {
const { rerender } = render();
const input = await screen.findByLabelText(label);
expect(input).toBeChecked();
rerender();
expect(input).not.toBeChecked();
});
it('should set the input to checked with the defaultChecked prop', () => {
const { container } = render(
);
const field = container.getElementsByTagName('input')[0];
expect(field).toBeChecked();
});
it('should set the id on the input element', () => {
const { container } = render(
);
const field = container.getElementsByTagName('input')[0];
expect(field.id).toEqual('my-switch');
});
it('should render labeled radio 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);
});
});
describe('Switch Track', () => {
it('should render the state classes on SwitchField', () => {
const { container } = render(
);
const wrapper = container.getElementsByClassName(
ComponentClassNames.SwitchTrack
)[0];
expect(wrapper).toHaveClass(
`${ComponentClassNames.SwitchTrack}--checked`
);
expect(wrapper).toHaveClass(
`${ComponentClassNames.SwitchTrack}--disabled`
);
});
it('should set the track color for the unchecked switch', () => {
const { container } = render(
);
const track = container.getElementsByClassName(
ComponentClassNames.SwitchTrack
)[0] as HTMLElement;
expect(
track.style.getPropertyValue(
kebabCase(ComponentPropsToStylePropsMap.backgroundColor)
)
).toBe('red');
});
it('should set the track color for the checked switch field', () => {
const { container } = render(
);
const track = container.getElementsByClassName(
ComponentClassNames.SwitchTrack
)[0] as HTMLElement;
expect(
track.style.getPropertyValue(
kebabCase(ComponentPropsToStylePropsMap.backgroundColor)
)
).toBe('red');
});
it('should add the data-focused attribute to the track when the input is focused', () => {
const { container } = render();
const track = container.getElementsByClassName(
ComponentClassNames.SwitchTrack
)[0] as HTMLElement;
const inputField = container.getElementsByTagName('input')[0];
inputField.focus();
expect(track).toHaveAttribute('data-focused');
});
});
describe('Switch Thumb', () => {
it('should change the switch thumb color', () => {
const { container } = render(
);
const track = container.getElementsByClassName(
ComponentClassNames.SwitchThumb
)[0] as HTMLElement;
expect(
track.style.getPropertyValue(
kebabCase(ComponentPropsToStylePropsMap.backgroundColor)
)
).toBe('red');
});
});
});