Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(form-field): Add testing-library/react and cypress tests #482

Merged
merged 13 commits into from
Mar 13, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions cypress/integration/FormField.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as h from '../helpers';

const getInput = () => {
return cy.get(`input`);
};

describe('Form Field', () => {
before(() => {
h.stories.visit();
});

context(`given the Default story is rendered`, () => {
beforeEach(() => {
h.stories.load('Components|Inputs/Form Field/React', 'Default');
});

it('should pass accessibility checks', () => {
cy.checkA11y();
});

context('when clicking on the label', () => {
beforeEach(() => {
cy.findByLabelText('Label').click();
});

it('should focus the input', () => {
getInput().should('be.focused');
});
});
});

['Hint Alert', 'Hint Error'].forEach(story => {
context(`given the '${story}' story is rendered`, () => {
beforeEach(() => {
h.stories.load('Components|Inputs/Form Field/React', story);
});

it('should pass accessibility and connect the input with the hint text', () => {
cy.checkA11y();
getInput().should('have.attr', 'aria-describedby');
});
});
});

context(`given the Label Required story is rendered`, () => {
beforeEach(() => {
h.stories.load('Components|Inputs/Form Field/React', 'Label Required');
});

it('should pass accessibility and connect the input with the hint text', () => {
cy.get('abbr').should('have.attr', 'title', 'required');
});
});
});
227 changes: 92 additions & 135 deletions modules/form-field/react/spec/FormField.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,152 +1,109 @@
import * as React from 'react';
import {mount} from 'enzyme';
import {GrowthBehavior} from '@workday/canvas-kit-react-common';
import FormField, {FormFieldErrorBehavior} from '../lib/FormField';
import {render} from '@testing-library/react';
import FormField from '../lib/FormField';
import {ErrorType} from '@workday/canvas-kit-react-common';

describe('FormField', () => {
test('Set a string label', () => {
const label = 'Label';
const component = mount(
<FormField label={label}>
<input type="text" />
</FormField>
);

expect(component.find('label').text()).toBe(label);

component.unmount();
});

test('Set a custom component', () => {
const label = <label>Custom Label</label>;
const component = mount(
<FormField label={label}>
<input type="text" />
</FormField>
);

expect(component.contains(label)).toBeDefined();

component.unmount();
});

test('Set hint text', () => {
const hintText = 'Hint Text';
const component = mount(
<FormField hintText={hintText}>
<input type="text" />
</FormField>
);

expect(component.render().text()).toEqual(expect.stringContaining(hintText));

component.unmount();
const cb = jest.fn();
afterEach(() => {
cb.mockReset();
});

test('Set aria-describedby', () => {
const InputComponent: React.FunctionComponent<GrowthBehavior> = () => <input type="text" />;
const hintText = 'Hint Text';
const hintId = 'hint-id';
const component = mount(
<FormField error={FormField.ErrorType.Error} hintText={hintText} hintId={hintId}>
<InputComponent />
</FormField>
);

expect(
component
.find('Hint')
.at(0)
.prop('id')
).toEqual(hintId);
expect(component.find(InputComponent).prop('aria-describedby')).toEqual(hintId);

component.unmount();
describe('when rendered', () => {
it('should render a label with text Label', () => {
const label = 'Label';
const {container} = render(
mannycarrera4 marked this conversation as resolved.
Show resolved Hide resolved
<FormField label={label}>
<input type="text" />
</FormField>
);
expect(container.querySelector('label')).toContainHTML('Label');
mannycarrera4 marked this conversation as resolved.
Show resolved Hide resolved
});
});

test('Sets id on input & htmlFor on label', () => {
const InputComponent: React.FunctionComponent = () => <input type="text" />;
const inputId = 'input-id';

const component = mount(
<FormField inputId={inputId} label="Label">
<InputComponent />
</FormField>
);

expect(component.find(InputComponent).prop('id')).toEqual(inputId);
expect(component.find('Label').prop('htmlFor')).toEqual(inputId);

component.unmount();
describe('when rendered with hint text', () => {
it('should render text below the input component', () => {
const label = 'Label';
const hintText = 'Helpful text goes here.';
const {container} = render(
<FormField hintText={hintText} label={label}>
<input type="text" />
</FormField>
);

expect(container.querySelector('p')).toContainHTML('Helpful text goes here.');
mannycarrera4 marked this conversation as resolved.
Show resolved Hide resolved
});
});

test('Sets grow prop', () => {
const InputComponent: React.FunctionComponent<GrowthBehavior> = () => <input type="text" />;

const component = mount(
<FormField grow={true}>
<InputComponent />
</FormField>
);

expect(component.find(InputComponent).props().grow).toEqual(true);

component.unmount();
describe('when rendered as required', () => {
it('should add a required element to the label to indicate that it is required', () => {
const label = 'Label';
const {getByText} = render(
<FormField label={label} required={true}>
<input type="text" />
</FormField>
);

expect(getByText('*')).toHaveAttribute('title', 'required');
});
});

test('Sets error prop with aria label', () => {
const InputComponent: React.FunctionComponent<FormFieldErrorBehavior> = () => (
<input type="text" />
);

const component = mount(
<FormField error={FormField.ErrorType.Error}>
<InputComponent />
</FormField>
);

expect(component.find(InputComponent).props().error).toEqual(FormField.ErrorType.Error);
expect(component.find(InputComponent).prop('aria-invalid')).toBeTruthy();

component.unmount();
describe('when rendered with useFieldset set to true', () => {
it('should render the FormField using a fieldset and a legend instead of a div and a label', () => {
const label = 'Label';
const {container} = render(
<FormField useFieldset={true} label={label} required={true}>
<input type="text" />
</FormField>
);

const fieldset = container.querySelector('fieldset');
expect(container).toContainElement(fieldset);
expect(container).toContainHTML('legend');
});
});

test('String child', () => {
const component = mount(<FormField>Text</FormField>);

expect(component.children().text()).toBe('Text');

component.unmount();
describe('when rendered with extra, arbitrary props', () => {
it('should spread extra props onto the form field', () => {
const attr = 'test';
const label = 'Label';
const {container} = render(
<FormField label={label} data-propspread={attr}>
<input type="text" />
</FormField>
);

expect(container.querySelector('div')).toHaveAttribute('data-propspread', 'test');
});
});

test('Uses fieldset and legend when useFieldset=true (for RadioGroup)', () => {
const InputComponent: React.FunctionComponent<FormFieldErrorBehavior> = () => (
<input type="text" />
);

const component = mount(
<FormField useFieldset={true} label="Label">
<InputComponent />
</FormField>
);

expect(component.find('fieldset')).toHaveLength(1);
expect(component.find('legend')).toHaveLength(1);

component.unmount();
describe('when rendered a hint id', () => {
it('the input and hint text should have matching ids for accessibility', () => {
const label = 'Label';
const hintId = 'hintId';
const hintText = 'Helpful text goes here.';
const {container} = render(
<FormField error={ErrorType.Error} hintId={hintId} hintText={hintText} label={label}>
<input type="text" />
</FormField>
);

expect(container.querySelector('p')).toHaveAttribute('id', 'hintId');
expect(container.querySelector('input')).toHaveAttribute('aria-describedby', 'hintId');
});
});

test('FormField should spread extra props', () => {
const InputComponent: React.FunctionComponent<FormFieldErrorBehavior> = () => (
<input type="text" />
);
const component = mount(
<FormField data-propspread="test">
<InputComponent />
</FormField>
);
const container = component.at(0).getDOMNode();
expect(container.getAttribute('data-propspread')).toBe('test');
component.unmount();
describe('when rendered a input id', () => {
it('the input and label should have matching ids for accessibility', () => {
const label = 'Label';
const inputId = 'inputId';
const hintText = 'Helpful text goes here.';
const {container} = render(
<FormField inputId={inputId} hintText={hintText} label={label}>
<input type="text" />
</FormField>
);

expect(container.querySelector('label')).toHaveAttribute('for', 'inputId');
expect(container.querySelector('input')).toHaveAttribute('id', 'inputId');
});
});
});
Loading