Skip to content

Commit

Permalink
feat #3 - Input field component (#53)
Browse files Browse the repository at this point in the history
* feat #3  - Create input field component + refactor button component + bump storybook version and fix glob error

Closes #3
  • Loading branch information
nancy-dassana authored Aug 21, 2020
1 parent 946ca1a commit cc4fdff
Show file tree
Hide file tree
Showing 10 changed files with 676 additions and 237 deletions.
2 changes: 1 addition & 1 deletion .storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = {
stories: ['../src/**/*.stories.(ts|tsx|js|jsx|mdx)'],
stories: ['../src/**/*.stories.@(ts|tsx|js|jsx|mdx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
Expand Down
431 changes: 212 additions & 219 deletions package-lock.json

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-jss": "^10.4.0",
"react-loading-skeleton": "^2.1.1",
"react-scripts": "^3.4.3",
"rollup": "^2.23.0",
"rollup-plugin-typescript2": "^0.27.1",
Expand Down Expand Up @@ -59,13 +60,13 @@
]
},
"devDependencies": {
"@storybook/addon-actions": "^6.0.12",
"@storybook/addon-essentials": "^6.0.12",
"@storybook/addon-links": "^6.0.12",
"@storybook/addon-storyshots": "^6.0.12",
"@storybook/addons": "^6.0.12",
"@storybook/addon-actions": "^6.0.16",
"@storybook/addon-essentials": "^6.0.16",
"@storybook/addon-links": "^6.0.16",
"@storybook/addon-storyshots": "^6.0.16",
"@storybook/addons": "^6.0.16",
"@storybook/preset-create-react-app": "^3.1.4",
"@storybook/react": "^6.0.12",
"@storybook/react": "^6.0.16",
"@types/classnames": "^2.2.10",
"@types/enzyme": "^3.10.5",
"@types/enzyme-adapter-react-16": "^1.0.6",
Expand Down
108 changes: 108 additions & 0 deletions src/__snapshots__/storybook.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,114 @@ exports[`Storyshots Button Primary Disabled 1`] = `
</button>
`;

exports[`Storyshots InputField Default 1`] = `
<div
className="container-0-2-3 container-d0-0-2-8"
>
<div
className="label-0-2-6"
>
Field Label
</div>
<input
className="ant-input"
disabled={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder=""
type="text"
value=""
/>
</div>
`;

exports[`Storyshots InputField Error 1`] = `
<div
className="container-0-2-3 container-d4-0-2-12"
>
<div
className="label-0-2-6"
>
Field Label
</div>
<input
className="ant-input error-0-2-4"
disabled={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder=""
type="text"
value=""
/>
</div>
`;

exports[`Storyshots InputField Full Width 1`] = `
<div
className="container-0-2-3 container-d3-0-2-11"
>
<div
className="label-0-2-6"
>
Field Label
</div>
<input
className="ant-input"
disabled={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder=""
type="text"
value=""
/>
</div>
`;

exports[`Storyshots InputField Loading 1`] = `
<div
className="container-0-2-3 container-d2-0-2-10"
>
<div
className="label-0-2-6"
>
<span>
<span
className="react-loading-skeleton css-1vmnjpn-skeletonStyles-Skeleton"
style={
Object {
"width": 100,
}
}
>
</span>
</span>
</div>
<div
className="input-0-2-5"
>
<span>
<span
className="react-loading-skeleton css-1vmnjpn-skeletonStyles-Skeleton"
style={
Object {
"height": 13,
}
}
>
</span>
</span>
</div>
</div>
`;

exports[`Storyshots Link Default 1`] = `
<a
className="ant-typography"
Expand Down
15 changes: 5 additions & 10 deletions src/components/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,28 @@ import { Meta, Story } from '@storybook/react/types-6-0'
export default {
argTypes: {
children: { control: 'text' },
classes: { control: 'array' }
classes: { control: 'array' },
onClick: { defaultValue: action('onClick') }
},
component: Button,
title: 'Button'
} as Meta

const actionsData = {
onClick: action('onClick')
}

const Template: Story<ButtonProps> = args => (
<Button {...args}>{args.children}</Button>
)

export const Default = Template.bind({})
Default.args = { ...actionsData, children: 'Default' }
Default.args = { children: 'Default' }

export const Disabled = Template.bind({})
Disabled.args = { ...actionsData, children: 'Disabled', disabled: true }
Disabled.args = { children: 'Disabled', disabled: true }

export const Primary = Template.bind({})
Primary.args = { ...actionsData, children: 'Primary', primary: true }
Primary.args = { children: 'Primary', primary: true }

export const PrimaryDisabled = Template.bind({})
PrimaryDisabled.args = {
...actionsData,
children: 'Primary Disabled',
disabled: true,
primary: true
Expand Down Expand Up @@ -65,7 +61,6 @@ const GoogleTemplate: Story<ButtonProps> = ({ ...args }: ButtonProps) => {

export const Google = GoogleTemplate.bind({})
Google.args = {
...actionsData,
children: 'Sign in with Google',
classes: ['google']
}
1 change: 0 additions & 1 deletion src/components/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'antd/lib/button/style/index.css'
import { Button as AntDButton } from 'antd'
import { ButtonProps as AntDButtonProps } from 'antd/es/button'
import classnames from 'classnames'

import React, { FC, ReactNode } from 'react'

export interface ButtonProps {
Expand Down
26 changes: 26 additions & 0 deletions src/components/InputField/InputField.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react'
import InputField, { InputFieldProps } from './index'
import { Meta, Story } from '@storybook/react/types-6-0'

export default {
argTypes: {
classes: { control: 'array' },
fieldLabel: { defaultValue: 'Field Label' },
value: { control: { disable: true } }
},
component: InputField,
title: 'InputField'
} as Meta

const Template: Story<InputFieldProps> = args => <InputField {...args} />

export const Default = Template.bind({})

export const Loading = Template.bind({})
Loading.args = { loading: true }

export const FullWidth = Template.bind({})
FullWidth.args = { fullWidth: true }

export const Error = Template.bind({})
Error.args = { error: true }
140 changes: 140 additions & 0 deletions src/components/InputField/InputField.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { Input } from 'antd'
import React from 'react'
import Skeleton from 'react-loading-skeleton'
import InputField, { InputFieldProps } from './index'
import { mount, ReactWrapper, shallow } from 'enzyme'

let wrapper: ReactWrapper

const mockProps: InputFieldProps = {
fieldLabel: 'Field Label'
}

beforeEach(() => {
wrapper = mount(<InputField {...mockProps} />)
})

describe('InputField', () => {
it('renders', () => {
const inputField = wrapper.find(InputField)

expect(inputField).toHaveLength(1)
})

it('renders a label if one exists', () => {
const inputField = wrapper.find(InputField)

expect(inputField.text()).toContain('Field Label')
})

it('throws an error if value is passed without an onClick', () => {
expect(() => shallow(<InputField value='abc' />)).toThrow()
})

it('should pass onChange and value to the input component if the props exist', () => {
const mockOnChange = jest.fn()
wrapper = mount(<InputField onChange={mockOnChange} value='abc' />)

expect(wrapper.find(Input).props().onChange).toEqual(mockOnChange)
expect(wrapper.find(Input).props().value).toEqual('abc')
})

it('correctly passes the disabled prop', () => {
wrapper = mount(<InputField disabled />)

expect(wrapper.find(Input).props().disabled).toBeTruthy()
})

it('correctly passes the placeholder prop', () => {
wrapper = mount(<InputField placeholder='Testing' />)

expect(wrapper.find(Input).props().placeholder).toEqual('Testing')
})

describe('type', () => {
it('defaults to type text if no type is specified', () => {
expect(wrapper.find(Input).props().type).toEqual('text')
})

it('correctly passes the input type prop', () => {
wrapper = mount(<InputField type='password' />)

expect(wrapper.find(Input).props().type).toEqual('password')
})
})

describe('loading', () => {
it('renders a loading skeleton', () => {
wrapper = mount(<InputField loading />)

expect(wrapper.find(Skeleton)).toHaveLength(1)
})

it('renders a loading skeleton for the label if there is one', () => {
wrapper = mount(<InputField fieldLabel='test' loading />)

expect(wrapper.find(Skeleton)).toHaveLength(2)
})
})

describe('fullWidth', () => {
beforeEach(() => {
// Mounting to document.body throws a React error, so create a temporary container div for the tests to mount the element to
const div = document.createElement('div')
div.setAttribute('id', 'container')
document.body.appendChild(div)
})

afterEach(() => {
const div = document.getElementById('container')

if (div) {
document.body.removeChild(div)
}
})

it('renders a container that will span the width of its parent container if set to true', () => {
wrapper = mount(<InputField fullWidth />, {
attachTo: document.getElementById('container')
})

const element = document.getElementsByClassName(
wrapper.getDOMNode().className
)[0]
const style = window.getComputedStyle(element)

expect(style.width).toEqual('100%')
})

it('does not render a container that will span the width of its parent container by default', () => {
wrapper = mount(<InputField />, {
attachTo: document.getElementById('container')
})

const element = document.getElementsByClassName(
wrapper.getDOMNode().className
)[0]
const style = window.getComputedStyle(element)

expect(style.width).not.toEqual('100%')
})
})

describe('required', () => {
it('passes the correct required class to field label container', () => {
wrapper = mount(<InputField fieldLabel='Field Label' required />)

expect(wrapper.getDOMNode().children[0].className).toContain(
'required'
)
})
})

describe('error', () => {
it('passes the correct error class to input', () => {
wrapper = mount(<InputField error />)

expect(wrapper.find(Input).hasClass(/error-*/)).toBeTruthy()
})
})
})
Loading

0 comments on commit cc4fdff

Please sign in to comment.