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(text-input): Change tests to react-testing-library and improve coverage #390

Merged
merged 17 commits into from
Jan 24, 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
46 changes: 46 additions & 0 deletions cypress/integration/TextInput.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as h from '../helpers';

const getTextInput = () => {
return cy.get(`[type="text"]`);
};

describe('TextInput', () => {
before(() => {
h.stories.visit();
});
['Default', 'Alert', 'Error'].forEach(story => {
context(`given the '${story}' story is rendered`, () => {
beforeEach(() => {
h.stories.load('Components|Inputs/Text Input/React/Top Label', story);
});

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

context('when clicked', () => {
beforeEach(() => {
getTextInput().click();
});

it('should be focused', () => {
getTextInput().should('be.focused');
});
});
});
});

context(`given the 'Disabled' story is rendered`, () => {
beforeEach(() => {
h.stories.load('Components|Inputs/Text Input/React/Top Label', 'Disabled');
});

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

it('should be disabled', () => {
getTextInput().should('be.disabled');
});
});
});
1 change: 1 addition & 0 deletions modules/_labs/core/react/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import CanvasProvider from './lib/CanvasProvider';
export default type;
export {type, space, CanvasProvider};
export * from './lib/type';
export * from './lib/StaticStates';
anicholls marked this conversation as resolved.
Show resolved Hide resolved
export * from './lib/theming';
51 changes: 51 additions & 0 deletions modules/form-field/react/stories/stories_TextInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/// <reference path="../../../../typings.d.ts" />
import * as React from 'react';
import {storiesOf} from '@storybook/react';
import {StaticStates} from '@workday/canvas-kit-labs-react-core';
import withReadme from 'storybook-readme/with-readme';
import {controlComponent} from '../../../../utils/storybook';

Expand Down Expand Up @@ -152,3 +153,53 @@ storiesOf('Components|Inputs/Text Input/React/Left Label', module)
{controlComponent(<TextInput placeholder="Placeholder" />)}
</FormField>
));

storiesOf('Components|Inputs/Text Input/React/Visual Testing', module)
.addParameters({component: TextInput})
.addDecorator(withReadme(README))
.add('States', () => (
<StaticStates>
<table>
<thead>
<tr>
<th></th>
<th>No state</th>
<th>Hover</th>
<th>Focused</th>
<th>Active</th>
</tr>
</thead>
<tbody>
{[false, true].map(disabled => {
return ['Default', 'Alert', 'Error'].map(variant => {
const type =
variant === 'Alert'
? FormField.ErrorType.Alert
: variant === 'Error'
? FormField.ErrorType.Error
: undefined;

const key = `${disabled ? 'disabled' : 'enabled'}-${variant}`;

return (
<tr key={key}>
<td>{`${disabled ? 'Disabled ' : ''}${variant}`}</td>

{['', 'hover', 'focus', 'active'].map(className => (
<td key={`${key}-${className}`}>
<TextInput
disabled={disabled}
error={type}
className={className}
onChange={() => {}} // eslint-disable-line no-empty-function
/>
</td>
))}
</tr>
);
});
})}
</tbody>
</table>
</StaticStates>
));
100 changes: 61 additions & 39 deletions modules/text-input/react/spec/TextInput.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,72 @@
import * as React from 'react';
import {mount} from 'enzyme';
import ReactDOMServer from 'react-dom/server';
import {render, fireEvent} from '@testing-library/react';
import TextInput from '../lib/TextInput';
import ReactDOMServer from 'react-dom/server';
stephanerangaya marked this conversation as resolved.
Show resolved Hide resolved
import {axe} from 'jest-axe';
import FormField from '@workday/canvas-kit-react-form-field';

describe('TextInput', () => {
test('TextInput should spread extra props', () => {
const component = mount(<TextInput data-propspread="test" onChange={jest.fn()} />);
const input = component
.find('input') // TODO: Standardize on prop spread location (see #150)
.getDOMNode();
expect(input.getAttribute('data-propspread')).toBe('test');
component.unmount();
const id = 'Test Text Input';
const label = 'Test Text Input';
const placeholder = 'Test Text Input';
const value = 'Test Text Input';

describe('Text Input', () => {
const cb = jest.fn();
afterEach(() => {
cb.mockReset();
});
});

describe('Text Input Accessibility', () => {
test('Text Input in a FormField should pass axe DOM accessibility guidelines', async () => {
const html = ReactDOMServer.renderToString(
<FormField
label="My Field"
inputId="my-input-field"
hintText="Helpful text to resolve error"
hintId="my-input-field-error"
error={FormField.ErrorType.Error}
>
<TextInput placeholder="Placeholder" value={'Hello'} onChange={jest.fn()} />;
</FormField>
);
expect(await axe(html)).toHaveNoViolations();
describe('when rendered', () => {
describe('with an placeholder', () => {
it('should render a text input with placeholder', () => {
const {getByPlaceholderText} = render(
stephanerangaya marked this conversation as resolved.
Show resolved Hide resolved
<TextInput onChange={cb} placeholder={placeholder} />
);
expect(getByPlaceholderText(placeholder)).toHaveAttribute('placeholder', placeholder);
});
});

describe('with a id', () => {
it('should render a text input with a id', () => {
const {getByPlaceholderText} = render(
<TextInput id={id} onChange={cb} value={value} placeholder={placeholder} />
);
expect(getByPlaceholderText(placeholder)).toHaveAttribute('id', id);
});
});

describe('with a value', () => {
it('should render a text input with a value', () => {
const {getByDisplayValue} = render(<TextInput onChange={cb} value={value} />);
expect(getByDisplayValue(value)).toBeDefined();
});
});

describe('with disabled attribute', () => {
it('should render a disabled text input', () => {
const {getByDisplayValue} = render(
<TextInput onChange={cb} disabled={true} value={value} />
);
expect(getByDisplayValue(value)).toBeDisabled();
});
});

describe('with extra, arbitrary props', () => {
it('should spread extra props onto the text input', () => {
const attr = 'test';
const {getByPlaceholderText} = render(
<TextInput onChange={cb} data-propspread={attr} placeholder={placeholder} />
);
expect(getByPlaceholderText(placeholder)).toHaveAttribute('data-propspread', attr);
});
});
});

test('Text Input with `aria-labelledby` should pass axe DOM accessibility guidelines', async () => {
const html = ReactDOMServer.renderToString(
<>
<label id="123">Label</label>
<TextInput
placeholder="Placeholder"
value={'Hello'}
aria-labelledby="123"
onChange={jest.fn()}
/>
;
</>
);
expect(await axe(html)).toHaveNoViolations();
describe('when provided an input ref', () => {
it('should render a text input with ref defined', () => {
const ref: React.RefObject<HTMLInputElement> = React.createRef();
render(<TextInput inputRef={ref} />);
expect(ref.current).toBeDefined();
stephanerangaya marked this conversation as resolved.
Show resolved Hide resolved
});
});
});