From 3b0ec725485476bd182a3147fc80816d4fc82a5f Mon Sep 17 00:00:00 2001 From: Ian Stewart Date: Mon, 13 Nov 2017 17:11:33 +0100 Subject: [PATCH] Issue #552 commands (#966) * Added getStyle test for Commands. * New structure for correct testing. * WIP Index Test for commands. * Added index test for commands. --- src/commands/{index.jsx => component.jsx} | 16 +-- src/commands/index.js | 13 ++ test/commands/get-styles.test.js | 104 ++++++++++++++ test/commands/index.test.js | 163 ++++++++++++++++++++++ 4 files changed, 283 insertions(+), 13 deletions(-) rename src/commands/{index.jsx => component.jsx} (95%) create mode 100644 src/commands/index.js create mode 100644 test/commands/get-styles.test.js create mode 100644 test/commands/index.test.js diff --git a/src/commands/index.jsx b/src/commands/component.jsx similarity index 95% rename from src/commands/index.jsx rename to src/commands/component.jsx index 3a97f28f..73de7987 100644 --- a/src/commands/index.jsx +++ b/src/commands/component.jsx @@ -1,15 +1,11 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import Radium from 'radium'; -import compose from 'recompose/compose'; import map from 'lodash/map'; import size from 'lodash/size'; import filter from 'lodash/filter'; import isEmpty from 'lodash/isEmpty'; import noop from 'lodash/noop'; -import onClickOutside from 'react-onclickoutside'; import EventListener from 'react-event-listener'; -import themeable from '../themeable'; import getStyles from './get-styles'; import Avatar from '../avatar'; import styles from './styles'; @@ -108,14 +104,14 @@ class Commands extends Component { } componentWillReceiveProps(nextProps) { - const { value } = nextProps; + const { value, commands } = nextProps; const { open } = this.state; if (!value) { return this.hideMenu(); } - const filteredCommands = this.filterCommands(nextProps.commands, nextProps.value); + const filteredCommands = this.filterCommands(commands, value); if (!isEmpty(filteredCommands) && !open) { this.setState({ @@ -318,10 +314,4 @@ Commands.displayName = 'Commands'; Commands.propTypes = propTypes; Commands.defaultProps = defaultProps; -const enhance = compose( - themeable(), - onClickOutside, - Radium -); - -export default enhance(Commands); +export default Commands; diff --git a/src/commands/index.js b/src/commands/index.js new file mode 100644 index 00000000..d13c3e5c --- /dev/null +++ b/src/commands/index.js @@ -0,0 +1,13 @@ +import Radium from 'radium'; +import compose from 'recompose/compose'; +import onClickOutside from 'react-onclickoutside'; +import themeable from '../themeable'; +import Commands from './component'; + +const enhance = compose( + themeable(), + onClickOutside, + Radium +); + +export default enhance(Commands); diff --git a/test/commands/get-styles.test.js b/test/commands/get-styles.test.js new file mode 100644 index 00000000..0ef872e3 --- /dev/null +++ b/test/commands/get-styles.test.js @@ -0,0 +1,104 @@ +/* eslint-env mocha */ +import { expect } from 'chai'; +import getStyles from '../../src/commands/get-styles'; +import styles from '../../src/commands/styles'; + +describe('Commands.getStyles', () => { + describe('root', () => { + it('should get styles', () => { + const style = getStyles.root(); + + expect(style).to.deep.equal(styles.root); + }); + + it('should combine styles', () => { + const style = getStyles.root({ color: 'red' }); + + expect(style).to.have.property('color', 'red'); + }); + }); + + describe('header', () => { + it('should get styles', () => { + const style = getStyles.header(); + + expect(style).to.deep.equal(styles.header); + }); + + it('should combine styles', () => { + const style = getStyles.header({ color: 'red' }); + + expect(style).to.have.property('color', 'red'); + }); + }); + + describe('commands', () => { + it('should get styles', () => { + const style = getStyles.commands(); + + expect(style).to.deep.equal(styles.commands); + }); + + it('should combine styles', () => { + const style = getStyles.commands({ color: 'red' }); + + expect(style).to.have.property('color', 'red'); + }); + }); + + describe('command', () => { + it('should get styles', () => { + const style = getStyles.command(); + + expect(style).to.deep.equal(styles.command); + }); + + it('should combine styles', () => { + const style = getStyles.command(undefined, false, { color: 'red' }); + + expect(style).to.have.property('color', 'red'); + }); + + it('should add active styles', () => { + const style = getStyles.command(undefined, true, {}); + + expect(style).to.have.property('backgroundColor', '#1BA6C4'); + expect(style).to.have.property('color', '#FEFEFE'); + }); + + it('should add color to active styles', () => { + const style = getStyles.command('HotPink', true, {}); + + expect(style).to.have.property('backgroundColor', 'HotPink'); + expect(style).to.have.property('color', '#FEFEFE'); + }); + }); + + describe('title', () => { + it('should get styles', () => { + const style = getStyles.title(); + + expect(style).to.deep.equal(styles.title); + }); + + it('should combine styles', () => { + const style = getStyles.title({ color: 'red' }); + + expect(style).to.have.property('color', 'red'); + }); + }); + + describe('description', () => { + it('should get styles', () => { + const style = getStyles.description(); + + expect(style).to.deep.equal(styles.description); + }); + + it('should combine styles', () => { + const style = getStyles.description({ color: 'red' }); + + expect(style).to.have.property('color', 'red'); + }); + }); +}); diff --git a/test/commands/index.test.js b/test/commands/index.test.js new file mode 100644 index 00000000..a449735a --- /dev/null +++ b/test/commands/index.test.js @@ -0,0 +1,163 @@ +/* eslint-env mocha */ +/* eslint react/jsx-filename-extension: [0] */ +import React from 'react'; +import chai, { expect } from 'chai'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import sinonChai from 'sinon-chai'; +import Commands from '../../src/commands/component'; +import getStyles from '../../src/commands/get-styles'; + +chai.use(sinonChai); + +describe('Commands', () => { + const props = { + commands: [ + { value: 'gif', prefix: '/' }, + { value: 'me', prefix: '@' } + ], + value: '', + style: {}, + headerStyle: {}, + titleStyle: {}, + commandStyle: {}, + descriptionStyle: {}, + onSelect: () => {}, + onChange: () => {}, + leading: true, + color: '#1BA6C4' + }; + + beforeEach(() => { + global.navigator = { userAgent: 'all' }; + }); + + afterEach(() => { + global.navigator = undefined; + }); + + it('should be an instanceOf Commands', () => { + const component = shallow(); + + expect(component.instance()).to.be.instanceOf(Commands); + }); + + it('should render root elements', () => { + const component = shallow(); + + component.setState({ open: true }); + expect(component.find('section')).to.have.length(2); + expect(component.find('header')).to.have.length(1); + }); + + it('should render command elements', () => { + const component = shallow(); + + component.setState({ open: true }); + expect(component.find('span')).to.have.length(2); + expect(component.find('span > strong')).to.have.length(2); + + component.setProps({ value: '/' }); + expect(component.find('span')).to.have.length(1); + expect(component.find('span > strong')).to.have.length(1); + }); + + it('should render command avatar element', () => { + const combinedProps = { + ...props, + commands: [ + { value: 'me', prefix: '@', avatar: 'image' } + ] + }; + const component = shallow(); + + component.setState({ open: true }); + expect(component.find('span')).to.have.length(1); + expect(component.find('span > strong')).to.have.length(1); + expect(component.find('span > div > Avatar')).to.have.length(1); + }); + + it('should render command param element', () => { + const combinedProps = { + ...props, + commands: [ + { value: 'gif', prefix: '/', param: 'text' } + ] + }; + const component = shallow(); + + component.setState({ open: true }); + expect(component.find('span')).to.have.length(2); + expect(component.find('span > strong')).to.have.length(1); + expect(component.find('span > span')).to.have.length(1); + expect(component.find('span > span').containsMatchingElement('text')).to.equal(true); + }); + + it('should render command description element', () => { + const combinedProps = { + ...props, + commands: [ + { value: 'me', prefix: '@', description: 'mention user' } + ] + }; + const component = shallow(); + + component.setState({ open: true }); + expect(component.find('span')).to.have.length(2); + expect(component.find('span > strong')).to.have.length(1); + expect(component.find('div > span')).to.have.length(2); + expect(component.find('div > span').containsMatchingElement('mention user')).to.equal(true); + }); + + it('should get root styles', () => { + const spy = sinon.spy(getStyles, 'root'); + const component = shallow(); + + component.setState({ open: true }); + expect(spy).to.have.been.calledWith(props.style); + }); + + it('should get header styles', () => { + const spy = sinon.spy(getStyles, 'header'); + const component = shallow(); + + component.setState({ open: true }); + expect(spy).to.have.been.calledWith(props.headerStyle); + }); + + it('should get commands styles', () => { + const spy = sinon.spy(getStyles, 'commands'); + const component = shallow(); + + component.setState({ open: true }); + expect(spy).to.have.callCount(1); + }); + + it('should get command styles', () => { + const spy = sinon.spy(getStyles, 'command'); + const component = shallow(); + + component.setState({ open: true }); + expect(spy).to.have.been.calledWith(props.color, false, props.commandStyle); + }); + + it('should get title styles', () => { + const spy = sinon.spy(getStyles, 'title'); + const component = shallow(); + + component.setState({ open: true }); + expect(spy).to.have.been.calledWith(props.titleStyle); + }); + + it('should get description styles', () => { + const spy = sinon.spy(getStyles, 'description'); + const combinedProps = { + ...props, + commands: [{ value: 'gif', prefix: '/', description: 'send gifs' }] + }; + const component = shallow(); + + component.setState({ open: true }); + expect(spy).to.have.been.calledWith(props.descriptionStyle); + }); +});