diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 000000000..0acbe04b1 --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,32 @@ +codecov: + notify: + require_ci_to_pass: yes + +coverage: + precision: 2 + round: down + range: "70...100" + + status: + project: yes + patch: yes + changes: no + +parsers: + gcov: + branch_detection: + conditional: yes + loop: yes + method: no + macro: no + +comment: + layout: "header, diff" + behavior: default + require_changes: no + +ignore: + - "__mocks__" + - "__tests__" + - "config" + - "static" diff --git a/README.md b/README.md index 7f5b1082c..c37c312ff 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,9 @@ yarn install && yarn start // Testing command yarn test +// Testing with debug (repl) command +yarn test:debug + // Distribution command yarn dist ``` diff --git a/__tests__/renderer/shared/components/Forms/Input/Input.test.js b/__tests__/renderer/shared/components/Forms/Input/Input.test.js new file mode 100644 index 000000000..1511cd043 --- /dev/null +++ b/__tests__/renderer/shared/components/Forms/Input/Input.test.js @@ -0,0 +1,22 @@ +import React from 'react'; +import { shallow } from 'enzyme'; + +import Input from 'shared/components/Forms/Input/Input'; + +const mountContainer = (props = {}) => { + return shallow(); +}; + +describe('', () => { + it('renders an input', () => { + const props = { id: 'name', defaultValue: 'foo' }; + const wrapper = mountContainer(props); + expect(wrapper.type()).toEqual('input'); + expect(wrapper.props()).toEqual(expect.objectContaining(props)); + }); + + it('applies a custom className', () => { + const wrapper = mountContainer({ className: 'passwordField' }); + expect(wrapper.prop('className').split(' ')).toContain('passwordField'); + }); +}); diff --git a/__tests__/renderer/shared/components/Forms/Input/index.test.js b/__tests__/renderer/shared/components/Forms/Input/index.test.js index 066cf9a85..ebbc72e1a 100644 --- a/__tests__/renderer/shared/components/Forms/Input/index.test.js +++ b/__tests__/renderer/shared/components/Forms/Input/index.test.js @@ -1,22 +1,16 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { mount } from 'enzyme'; -import Input from 'shared/components/Forms/Input'; +import InputContainer from 'shared/components/Forms/Input'; +import Input from 'shared/components/Forms/Input/Input'; const mountContainer = (props = {}) => { - return shallow(); + return mount(); }; describe('', () => { - it('renders an input', () => { - const props = { id: 'name', defaultValue: 'foo' }; - const wrapper = mountContainer(props); - expect(wrapper.type()).toEqual('input'); - expect(wrapper.props()).toEqual(expect.objectContaining(props)); - }); - - it('applies a custom className', () => { - const wrapper = mountContainer({ className: 'passwordField' }); - expect(wrapper.prop('className').split(' ')).toContain('passwordField'); + it('forwards the ref to the component', () => { + const wrapper = mountContainer({ ref: React.createRef() }); + expect(wrapper).toForwardRefTo(Input); }); }); diff --git a/__tests__/renderer/shared/components/Forms/LabeledInput/LabeledInput.test.js b/__tests__/renderer/shared/components/Forms/LabeledInput/LabeledInput.test.js new file mode 100644 index 000000000..b73226fc0 --- /dev/null +++ b/__tests__/renderer/shared/components/Forms/LabeledInput/LabeledInput.test.js @@ -0,0 +1,27 @@ +import React from 'react'; +import { mount } from 'enzyme'; + +import LabeledInput from 'shared/components/Forms/LabeledInput/LabeledInput'; +import Label from 'shared/components/Forms/Label'; +import Input from 'shared/components/Forms/Input'; + +const mountContainer = (props = {}) => { + return mount(); +}; + +describe('', () => { + it('renders a label', () => { + const wrapper = mountContainer({ id: 'name', label: 'Name' }); + const label = wrapper.find(Label); + expect(label.exists()).toBe(true); + expect(label.props()).toEqual(expect.objectContaining({ label: 'Name', htmlFor: 'name' })); + }); + + it('renders an input', () => { + const inputProps = { id: 'pw', type: 'password', defaultValue: 'foo' }; + const wrapper = mountContainer({ label: 'Password', ...inputProps }); + const input = wrapper.find(Input); + expect(input.exists()).toBe(true); + expect(input.props()).toEqual(expect.objectContaining(inputProps)); + }); +}); diff --git a/__tests__/renderer/shared/components/Forms/LabeledInput/index.test.js b/__tests__/renderer/shared/components/Forms/LabeledInput/index.test.js index a0b5155b2..f71116052 100644 --- a/__tests__/renderer/shared/components/Forms/LabeledInput/index.test.js +++ b/__tests__/renderer/shared/components/Forms/LabeledInput/index.test.js @@ -1,27 +1,16 @@ import React from 'react'; import { mount } from 'enzyme'; -import LabeledInput from 'shared/components/Forms/LabeledInput'; -import Label from 'shared/components/Forms/Label'; -import Input from 'shared/components/Forms/Input'; +import LabeledInputContainer from 'shared/components/Forms/LabeledInput'; +import LabeledInput from 'shared/components/Forms/LabeledInput/LabeledInput'; const mountContainer = (props = {}) => { - return mount(); + return mount(); }; describe('', () => { - it('renders a label', () => { - const wrapper = mountContainer({ id: 'name', label: 'Name' }); - const label = wrapper.find(Label); - expect(label.exists()).toBe(true); - expect(label.props()).toEqual(expect.objectContaining({ label: 'Name', htmlFor: 'name' })); - }); - - it('renders an input', () => { - const inputProps = { id: 'pw', type: 'password', defaultValue: 'foo' }; - const wrapper = mountContainer({ label: 'Password', ...inputProps }); - const input = wrapper.find(Input); - expect(input.exists()).toBe(true); - expect(input.props()).toEqual(expect.objectContaining(inputProps)); + it('forwards the ref to the component', () => { + const wrapper = mountContainer({ ref: React.createRef() }); + expect(wrapper).toForwardRefTo(LabeledInput); }); }); diff --git a/__tests__/renderer/shared/components/Forms/LabeledSelect/LabeledSelect.test.js b/__tests__/renderer/shared/components/Forms/LabeledSelect/LabeledSelect.test.js new file mode 100644 index 000000000..4ac267c7a --- /dev/null +++ b/__tests__/renderer/shared/components/Forms/LabeledSelect/LabeledSelect.test.js @@ -0,0 +1,32 @@ +import React from 'react'; +import { mount } from 'enzyme'; + +import LabeledSelect from 'shared/components/Forms/LabeledSelect'; +import Label from 'shared/components/Forms/Label'; +import Select from 'shared/components/Forms/Select'; + +const mountContainer = (props = {}) => { + return mount(); +}; + +describe('', () => { + it('renders a label', () => { + const wrapper = mountContainer({ id: 'currency', label: 'Currency' }); + const label = wrapper.find(Label); + expect(label.exists()).toBe(true); + expect(label.props()).toEqual(expect.objectContaining({ label: 'Currency', htmlFor: 'currency' })); + }); + + it('renders a select', () => { + const children = ( + + + + + ); + const wrapper = mountContainer({ id: 'currency', label: 'Currency', children }); + const select = wrapper.find(Select); + expect(select.exists()).toBe(true); + expect(select.props()).toEqual(expect.objectContaining({ id: 'currency', children })); + }); +}); diff --git a/__tests__/renderer/shared/components/Forms/LabeledSelect/index.test.js b/__tests__/renderer/shared/components/Forms/LabeledSelect/index.test.js index 4ac267c7a..7b82dd97a 100644 --- a/__tests__/renderer/shared/components/Forms/LabeledSelect/index.test.js +++ b/__tests__/renderer/shared/components/Forms/LabeledSelect/index.test.js @@ -1,32 +1,16 @@ import React from 'react'; import { mount } from 'enzyme'; -import LabeledSelect from 'shared/components/Forms/LabeledSelect'; -import Label from 'shared/components/Forms/Label'; -import Select from 'shared/components/Forms/Select'; +import LabeledSelectContainer from 'shared/components/Forms/LabeledSelect'; +import LabeledSelect from 'shared/components/Forms/LabeledSelect/LabeledSelect'; const mountContainer = (props = {}) => { - return mount(); + return mount(); }; describe('', () => { - it('renders a label', () => { - const wrapper = mountContainer({ id: 'currency', label: 'Currency' }); - const label = wrapper.find(Label); - expect(label.exists()).toBe(true); - expect(label.props()).toEqual(expect.objectContaining({ label: 'Currency', htmlFor: 'currency' })); - }); - - it('renders a select', () => { - const children = ( - - - - - ); - const wrapper = mountContainer({ id: 'currency', label: 'Currency', children }); - const select = wrapper.find(Select); - expect(select.exists()).toBe(true); - expect(select.props()).toEqual(expect.objectContaining({ id: 'currency', children })); + it('forwards the ref to the component', () => { + const wrapper = mountContainer({ ref: React.createRef() }); + expect(wrapper).toForwardRefTo(LabeledSelect); }); }); diff --git a/__tests__/renderer/shared/components/Forms/Select/Select.test.js b/__tests__/renderer/shared/components/Forms/Select/Select.test.js new file mode 100644 index 000000000..866de26b1 --- /dev/null +++ b/__tests__/renderer/shared/components/Forms/Select/Select.test.js @@ -0,0 +1,28 @@ +import React from 'react'; +import { shallow } from 'enzyme'; + +import Select from 'shared/components/Forms/Select/Select'; + +const mountContainer = (props = {}) => { + return shallow(', () => { + it('renders a select', () => { + const children = ( + + + + + ); + const props = { id: 'name', defaultValue: 'foo', children }; + const wrapper = mountContainer(props); + expect(wrapper.type()).toEqual('select'); + expect(wrapper.props()).toEqual(expect.objectContaining(props)); + }); + + it('applies a custom className', () => { + const wrapper = mountContainer({ className: 'currency' }); + expect(wrapper.prop('className').split(' ')).toContain('currency'); + }); +}); diff --git a/__tests__/renderer/shared/components/Forms/Select/index.test.js b/__tests__/renderer/shared/components/Forms/Select/index.test.js index a8c47019d..bf7082fc9 100644 --- a/__tests__/renderer/shared/components/Forms/Select/index.test.js +++ b/__tests__/renderer/shared/components/Forms/Select/index.test.js @@ -1,28 +1,16 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { mount } from 'enzyme'; -import Select from 'shared/components/Forms/Select'; +import SelectContainer from 'shared/components/Forms/Select'; +import Select from 'shared/components/Forms/Select/Select'; const mountContainer = (props = {}) => { - return shallow(', () => { - it('renders a select', () => { - const children = ( - - - - - ); - const props = { id: 'name', defaultValue: 'foo', children }; - const wrapper = mountContainer(props); - expect(wrapper.type()).toEqual('select'); - expect(wrapper.props()).toEqual(expect.objectContaining(props)); - }); - - it('applies a custom className', () => { - const wrapper = mountContainer({ className: 'currency' }); - expect(wrapper.prop('className').split(' ')).toContain('currency'); + it('forwards the ref to the component', () => { + const wrapper = mountContainer({ ref: React.createRef() }); + expect(wrapper).toForwardRefTo(Select); }); }); diff --git a/__tests__/setupFramework.js b/__tests__/setupFramework.js index 934d1289c..77dc81a26 100644 --- a/__tests__/setupFramework.js +++ b/__tests__/setupFramework.js @@ -1,3 +1,5 @@ +import { getDisplayName } from 'recompose'; + expect.extend({ toContainObject(received, argument) { const pass = this.equals( @@ -11,6 +13,16 @@ expect.extend({ ? () => `expected ${this.utils.printReceived(received)} not to contain object ${this.utils.printExpected(argument)}` : () => `expected ${this.utils.printReceived(received)} to contain object ${this.utils.printExpected(argument)}`; + return { pass, message }; + }, + + toForwardRefTo(received, argument) { + const pass = received.find('ForwardRef').find(argument).exists(); + + const message = pass + ? () => `expected to not forward ref to ${this.utils.printExpected(getDisplayName(argument))}` + : () => `expected to forward ref to ${this.utils.printExpected(getDisplayName(argument))}`; + return { pass, message }; } }); diff --git a/package.json b/package.json index 6c87e35db..cd9e1198b 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "pack": "yarn dist --dir -c.compression=store -c.mac.identity=null", "pretest": "yarn run lint && yarn run stylelint", "test": "jest", + "test:debug": "node inspect ./node_modules/.bin/jest --runInBand", "stylelint": "stylelint src/**/*.scss", "lint": "eslint --env browser,node,server --ext .jsx,.js --color .", "lint:fix": "yarn run lint --fix", diff --git a/src/renderer/shared/components/Forms/Button/Button.js b/src/renderer/shared/components/Forms/Button/Button.js index 0ec09f5e6..de44cea8e 100644 --- a/src/renderer/shared/components/Forms/Button/Button.js +++ b/src/renderer/shared/components/Forms/Button/Button.js @@ -1,39 +1,30 @@ import React from 'react'; import classNames from 'classnames'; -import { string } from 'prop-types'; +import { string, func } from 'prop-types'; +import { omit } from 'lodash'; import styles from './Button.scss'; export default class Button extends React.PureComponent { + static propTypes = { + className: string, + type: string, + forwardedRef: func + }; + + static defaultProps = { + className: null, + type: 'button', + forwardedRef: null + }; + render() { return ( // eslint-disable-next-line react/button-has-type