From daef2d75314e3f16d3c57daed3d663281bc78f1c Mon Sep 17 00:00:00 2001 From: yannis <yannisbarlas@gmail.com> Date: Tue, 22 Aug 2017 15:06:12 +0300 Subject: [PATCH] add more xpub ui unit tests --- .babelrc | 6 ++ package.json | 20 +++- test/AppBar.test.js | 113 ++++++++++++++++++++ test/Radio.test.js | 58 +++++++++++ test/RadioGroup.test.js | 116 +++++++++++++++++++++ test/YesOrNo.test.js | 57 ++++++++++ test/__snapshots__/AppBar.test.js.snap | 29 ++++++ test/__snapshots__/Radio.test.js.snap | 18 ++++ test/__snapshots__/RadioGroup.test.js.snap | 48 +++++++++ test/__snapshots__/YesOrNo.test.js.snap | 34 ++++++ test/setup/styleMock.js | 1 + 11 files changed, 497 insertions(+), 3 deletions(-) create mode 100644 .babelrc create mode 100644 test/AppBar.test.js create mode 100644 test/Radio.test.js create mode 100644 test/RadioGroup.test.js create mode 100644 test/YesOrNo.test.js create mode 100644 test/__snapshots__/AppBar.test.js.snap create mode 100644 test/__snapshots__/Radio.test.js.snap create mode 100644 test/__snapshots__/RadioGroup.test.js.snap create mode 100644 test/__snapshots__/YesOrNo.test.js.snap create mode 100644 test/setup/styleMock.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 000000000..2a4a32d91 --- /dev/null +++ b/.babelrc @@ -0,0 +1,6 @@ +{ + "presets": [ + "es2015", + "react" + ] +} \ No newline at end of file diff --git a/package.json b/package.json index 5e0804513..7c0d24f02 100644 --- a/package.json +++ b/package.json @@ -21,18 +21,28 @@ "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.2", + "babel-jest": "^20.0.3", + "babel-preset-es2015": "^6.24.1", "babel-preset-env": "^1.6.0", "babel-preset-minify": "^0.2.0", "babel-preset-react": "^6.24.1", "babel-preset-stage-2": "^6.24.1", "css-loader": "^0.28.4", + "enzyme": "^2.9.1", "faker": "^4.1.0", "file-loader": "^0.11.2", - "xpub-styleguide": "^0.0.2", + "jest": "^20.0.4", "react-styleguidist": "^6.0.8", + "react-test-renderer": "^15.6.1", "style-loader": "^0.18.2", "webpack": "^3.5.5", - "webpack-node-externals": "^1.6.0" + "webpack-node-externals": "^1.6.0", + "xpub-styleguide": "^0.0.2" + }, + "jest": { + "moduleNameMapper": { + "\\.(css|less)$": "<rootDir>/test/setup/styleMock.js" + } }, "scripts": { "styleguide": "styleguidist server", @@ -40,6 +50,10 @@ "clean": "rimraf dist", "lint": "eslint src", "prebuild": "npm run clean && npm run lint", - "build": "webpack --progress --profile" + "build": "webpack --progress --profile", + "test": "NODE_ENV=test jest", + "test:watch": "NODE_ENV=test jest --watch", + "test:cover": "NODE_ENV=test jest --coverage", + "test:u": "NODE_ENV=test jest --updateSnapshot" } } diff --git a/test/AppBar.test.js b/test/AppBar.test.js new file mode 100644 index 000000000..b0cc4289d --- /dev/null +++ b/test/AppBar.test.js @@ -0,0 +1,113 @@ +import React from 'react' +import { clone } from 'lodash' +import { shallow } from 'enzyme' +import { Link } from 'react-router' +import renderer from 'react-test-renderer' + +import AppBar from '../src/molecules/AppBar' + +const props = { + brandLink: 'some link', + brandName: 'some brand', + loginLink: 'login link', + logoutLink: 'logout link', + userName: 'some name', +} + +const wrapper = shallow(<AppBar {...props} />) + +describe('AppBar', () => { + test('Snapshot', () => { + const tree = renderer.create( + <AppBar {...props} /> + ).toJSON() + expect(tree).toMatchSnapshot() + }) + + test('Should render correctly', () => { + expect(wrapper.is('div')) + expect(wrapper.children()).toHaveLength(2) + + const brand = wrapper.childAt(0) + expect(brand.is(Link)).toBeTruthy() + expect(brand.children()).toHaveLength(1) + + const rightArea = wrapper.childAt(1) + expect(rightArea.is('div')).toBeTruthy() + expect(rightArea.children()).toHaveLength(2) + + const username = rightArea.childAt(0) + expect(username.is('span')).toBeTruthy() + + const logLink = rightArea.childAt(1) + expect(logLink.is(Link)).toBeTruthy() + }) + + test('Should link the brand to \'/\' if no brand link is given', () => { + const newProps = clone(props) + newProps.brandLink = undefined + const wrapper = shallow(<AppBar {...newProps} />) + + const brand = wrapper.childAt(0) + expect(brand.prop('to')).toBe('/') + }) + + test('Should link the brand to the given prop', () => { + const brand = wrapper.childAt(0) + expect(brand.prop('to')).toBe(props.brandLink) + }) + + test('Should display the brand name', () => { + const brand = wrapper.childAt(0) + const brandName = brand.childAt(0) + + expect(brandName.text()).toBe(props.brandName) + }) + + test('Should not display the username if there is none given', () => { + const newProps = clone(props) + newProps.userName = undefined + const wrapper = shallow(<AppBar {...newProps} />) + + const rightArea = wrapper.childAt(1) + + // If the username does not display, there is only child (login / logout) + expect(rightArea.children).toHaveLength(1) + }) + + test('Should display the username', () => { + const rightArea = wrapper.childAt(1) + expect(rightArea.children()).toHaveLength(2) + + const userName = rightArea.childAt(0) + expect(userName.text()).toBe(props.userName) + }) + + test('Should display the login link if no username is given', () => { + const newProps = clone(props) + newProps.userName = undefined + const wrapper = shallow(<AppBar {...newProps} />) + + const rightArea = wrapper.childAt(1) + const logLink = rightArea.childAt(0) // first el if there is no username + + expect(logLink.is(Link)).toBeTruthy() + expect(logLink.prop('to')).toBe(props.loginLink) + expect(logLink.children()).toHaveLength(1) + + const logLinkText = logLink.childAt(0) + expect(logLinkText.text()).toBe('login') + }) + + test('Should display the logout link if a username is found', () => { + const rightArea = wrapper.childAt(1) + const logLink = rightArea.childAt(1) // 2nd el if there is a username + + expect(logLink.is(Link)).toBeTruthy() + expect(logLink.prop('to')).toBe(props.logoutLink) + expect(logLink.children()).toHaveLength(1) + + const logLinkText = logLink.childAt(0) + expect(logLinkText.text()).toBe('logout') + }) +}) diff --git a/test/Radio.test.js b/test/Radio.test.js new file mode 100644 index 000000000..ef32d9dea --- /dev/null +++ b/test/Radio.test.js @@ -0,0 +1,58 @@ +import React from 'react' +import { shallow } from 'enzyme' +import renderer from 'react-test-renderer' + +import Radio from '../src/atoms/Radio' + +const props = { + checked: false, + handleChange: jest.fn(), + label: 'TestLabel', + name: 'TestName', + required: true, + value: 'TestValue' +} + +const wrapper = shallow(<Radio {...props} />) + +describe('Radio', () => { + test('Snapshot', () => { + const tree = renderer.create( + <Radio {...props} /> + ).toJSON() + expect(tree).toMatchSnapshot() + }) + + test('Renders correctly', () => { + expect(wrapper.is('label')).toBeTruthy() + expect(wrapper.children()).toHaveLength(2) + + const input = wrapper.childAt(0) + expect(input.is('input')).toBeTruthy() + expect(input.children()).toHaveLength(0) + + const labelText = wrapper.childAt(1) + expect(labelText.text()).toBe(props.label) + expect(labelText.children()).toHaveLength(0) + }) + + test('Input gets the correct props', () => { + const input = wrapper.find('input') + + expect(input.prop('name')).toBe(props.name) + expect(input.prop('value')).toBe(props.value) + expect(input.prop('checked')).toBe(props.checked) + expect(input.prop('required')).toBe(props.required) + }) + + test('Change handler should be called on change', () => { + const input = wrapper.find('input') + + expect(props.handleChange).not.toHaveBeenCalled() + + const event = { target: {} } + input.simulate('change', event) + + expect(props.handleChange).toHaveBeenCalledTimes(1) + }) +}) diff --git a/test/RadioGroup.test.js b/test/RadioGroup.test.js new file mode 100644 index 000000000..d2964e6d0 --- /dev/null +++ b/test/RadioGroup.test.js @@ -0,0 +1,116 @@ +import React from 'react' +import { clone } from 'lodash' +import { shallow } from 'enzyme' +import renderer from 'react-test-renderer' + +import Radio from '../src/atoms/Radio' +import RadioGroup from '../src/molecules/RadioGroup' + +const handleChange = () => { return null } + +const props = { + handleChange, + name: 'TestName', + options: [ + { + label: 'Yes', + value: 'yes' + }, + { + label: 'No', + value: 'no' + }, + { + label: 'Maybe', + value: 'maybe' + } + ], + required: true, + value: undefined +} + +const wrapper = shallow(<RadioGroup {...props} />) +const radios = wrapper.find(Radio) + +describe('Radio Group', () => { + test('Snapshot', () => { + const tree = renderer.create( + <RadioGroup {...props} /> + ).toJSON() + expect(tree).toMatchSnapshot() + }) + + test('Renders a number of radio buttons', () => { + expect(wrapper.is('div')).toBeTruthy() + + const len = props.options.length + expect(wrapper.children()).toHaveLength(len) + + let i = 0 + + while (i < len) { + const child = wrapper.childAt(i) + expect(child.is(Radio)).toBeTruthy() + + i++ + } + + expect(radios).toHaveLength(len) + }) + + test('Radios get the correct props', () => { + const radioComps = radios.getNodes() + let i = 0 + + while (i < props.options.length) { + const radio = radioComps[i] + const radioProps = radio.props + + expect(radioProps.label).toEqual(props.options[i].label) + expect(radioProps.value).toEqual(props.options[i].value) + expect(radioProps.name).toEqual(props.name) + expect(radioProps.required).toEqual(props.required) + expect(radioProps.handleChange).toEqual(props.handleChange) + + i++ + } + }) + + test('Value should match the checked radio button', () => { + // With no radio button selected + const radioComps = radios.getNodes() + let i = 0 + + while (i < props.options.length) { + const radio = radioComps[i] + const radioProps = radio.props + + expect(radioProps.checked).toBeFalsy() + i++ + } + + // With the first radio button selected + // (re-initialise the wrapper with changed props) + const newProps = clone(props) + newProps.value = 'yes' + + const newWrapper = shallow(<RadioGroup {...newProps} />) + const newRadios = newWrapper.find(Radio) + const newRadioComps = newRadios.getNodes() + + i = 0 + + while (i < props.options.length) { + const radio = newRadioComps[i] + const radioProps = radio.props + + if (i === 0) { + expect(radioProps.checked).toBeTruthy() + } else { + expect(radioProps.checked).toBeFalsy() + } + + i++ + } + }) +}) diff --git a/test/YesOrNo.test.js b/test/YesOrNo.test.js new file mode 100644 index 000000000..31bab793d --- /dev/null +++ b/test/YesOrNo.test.js @@ -0,0 +1,57 @@ +import React from 'react' +import { shallow } from 'enzyme' +import renderer from 'react-test-renderer' + +import YesOrNo from '../src/molecules/YesOrNo' +import RadioGroup from '../src/molecules/RadioGroup' + +const handleChange = () => { return null } + +const props = { + handleChange, + name: 'TestName', + value: 'Maybe' +} + +const wrapper = shallow(<YesOrNo {...props} />) +const radio = wrapper.find(RadioGroup) + +describe('Yes or No', () => { + test('Snapshot', () => { + const tree = renderer.create( + <YesOrNo {...props} /> + ).toJSON() + expect(tree).toMatchSnapshot() + }) + + test('Renders a RadioGroup', () => { + expect(wrapper.is('RadioGroup')).toBeTruthy() + expect(radio).toHaveLength(1) + }) + + test('Passes the correct options', () => { + const options = radio.props().options + expect(options).toHaveLength(2) + + expect(options[0].value).toEqual('yes') + expect(options[0].label).toEqual('Yes') + + expect(options[1].value).toEqual('no') + expect(options[1].label).toEqual('No') + }) + + test('Passes down the correct name', () => { + const name = radio.props().name + expect(name).toEqual(props.name) + }) + + test('Passes down the correct value', () => { + const value = radio.props().value + expect(value).toEqual(props.value) + }) + + test('Passes down the correct handle change function', () => { + const handle = radio.props().handleChange + expect(handle).toEqual(props.handleChange) + }) +}) diff --git a/test/__snapshots__/AppBar.test.js.snap b/test/__snapshots__/AppBar.test.js.snap new file mode 100644 index 000000000..3ea9dd76f --- /dev/null +++ b/test/__snapshots__/AppBar.test.js.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AppBar Snapshot 1`] = ` +<div + className={undefined} +> + <a + className={undefined} + onClick={[Function]} + style={Object {}} + > + some brand + </a> + <div> + <span + className={undefined} + > + some name + </span> + <a + className="" + onClick={[Function]} + style={Object {}} + > + logout + </a> + </div> +</div> +`; diff --git a/test/__snapshots__/Radio.test.js.snap b/test/__snapshots__/Radio.test.js.snap new file mode 100644 index 000000000..d13bda93e --- /dev/null +++ b/test/__snapshots__/Radio.test.js.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Radio Snapshot 1`] = ` +<label + className={undefined} +> + <input + checked={false} + className={undefined} + name="TestName" + onChange={[Function]} + required={true} + type="radio" + value="TestValue" + /> + TestLabel +</label> +`; diff --git a/test/__snapshots__/RadioGroup.test.js.snap b/test/__snapshots__/RadioGroup.test.js.snap new file mode 100644 index 000000000..6443d52a4 --- /dev/null +++ b/test/__snapshots__/RadioGroup.test.js.snap @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Radio Group Snapshot 1`] = ` +<div> + <label + className={undefined} + > + <input + checked={false} + className={undefined} + name="TestName" + onChange={[Function]} + required={true} + type="radio" + value="yes" + /> + Yes + </label> + <label + className={undefined} + > + <input + checked={false} + className={undefined} + name="TestName" + onChange={[Function]} + required={true} + type="radio" + value="no" + /> + No + </label> + <label + className={undefined} + > + <input + checked={false} + className={undefined} + name="TestName" + onChange={[Function]} + required={true} + type="radio" + value="maybe" + /> + Maybe + </label> +</div> +`; diff --git a/test/__snapshots__/YesOrNo.test.js.snap b/test/__snapshots__/YesOrNo.test.js.snap new file mode 100644 index 000000000..bfe7af7e3 --- /dev/null +++ b/test/__snapshots__/YesOrNo.test.js.snap @@ -0,0 +1,34 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Yes or No Snapshot 1`] = ` +<div> + <label + className={undefined} + > + <input + checked={false} + className={undefined} + name="TestName" + onChange={[Function]} + required={undefined} + type="radio" + value="yes" + /> + Yes + </label> + <label + className={undefined} + > + <input + checked={false} + className={undefined} + name="TestName" + onChange={[Function]} + required={undefined} + type="radio" + value="no" + /> + No + </label> +</div> +`; diff --git a/test/setup/styleMock.js b/test/setup/styleMock.js new file mode 100644 index 000000000..7c6d6c73d --- /dev/null +++ b/test/setup/styleMock.js @@ -0,0 +1 @@ +module.exports = {} \ No newline at end of file -- GitLab