Skip to content

Commit

Permalink
reorganize tests, use chrome until phantomjs works
Browse files Browse the repository at this point in the history
  • Loading branch information
echenley committed Nov 24, 2015
1 parent 0fd255f commit e706d48
Show file tree
Hide file tree
Showing 19 changed files with 384 additions and 400 deletions.
52 changes: 27 additions & 25 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,38 +1,34 @@
{
"name": "react-news",
"version": "0.1.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/echenley/react-news.git"
},
"dependencies": {
"babel-preset-es2015": "^6.1.2",
"babel-preset-react": "^6.1.2",
"babel-preset-stage-2": "^6.1.2",
"babel-runtime": "^6.0.14",
"classnames": "^2.2.0",
"firebase": "^2.3.1",
"md5": "^2.0.0",
"moment": "^2.10.6",
"react": "^0.14.2",
"react-addons-update": "^0.14.2",
"react-dom": "^0.14.2",
"react-router": "1.0.0-rc4",
"reflux": "^0.3.0"
},
"devDependencies": {
"autoprefixer": "^6.1.0",
"babel": "^6.0.15",
"babel-core": "^6.1.2",
"babel-eslint": "^4.1.4",
"babel-loader": "^6.0.1",
"babel-plugin-transform-runtime": "^6.1.18",
"babel-polyfill": "^6.2.0",
"babel-preset-es2015": "^6.1.2",
"babel-preset-react": "^6.1.2",
"babel-preset-stage-2": "^6.1.2",
"babel-runtime": "^6.2.0",
"chai": "^3.4.0",
"css-loader": "^0.22.0",
"chai-equal-jsx": "^1.0.8",
"classnames": "^2.2.0",
"css-loader": "^0.23.0",
"eslint": "^1.8.0",
"eslint-friendly-formatter": "^1.2.2",
"eslint-loader": "^1.1.1",
"eslint-plugin-react": "^3.7.1",
"history": "^1.13.1",
"expect": "^1.12.2",
"expect-jsx": "^2.1.0",
"firebase": "^2.3.1",
"history": "^1.13.0",
"html-webpack-plugin": "^1.6.2",
"istanbul-instrumenter-loader": "^0.1.3",
"jsdom": "^7.0.2",
Expand All @@ -48,31 +44,37 @@
"karma-sinon-chai": "^1.1.0",
"karma-sourcemap-loader": "^0.3.6",
"karma-webpack": "^1.7.0",
"lodash": "^3.10.1",
"md5": "^2.0.0",
"mocha": "^2.3.3",
"node-sass": "^3.4.2",
"moment": "^2.10.6",
"node-sass": "^3.4.1",
"null-loader": "^0.1.1",
"phantomjs": "^1.9.18",
"postcss-loader": "^0.7.0",
"postcss-loader": "^0.8.0",
"react": "^0.14.2",
"react-addons-test-utils": "^0.14.2",
"react-addons-update": "^0.14.2",
"react-dom": "^0.14.2",
"react-hot-loader": "^1.3.0",
"react-router": "^1.0.0-rc3",
"reflux": "^0.3.0",
"sass-loader": "^3.1.1",
"sinon": "^1.17.2",
"sinon-chai": "^2.8.0",
"style-loader": "^0.13.0",
"svg-inline-loader": "^0.3.0",
"svg-inline-loader": "^0.4.0",
"webpack": "^1.12.3",
"webpack-dev-server": "^1.12.1"
},
"engines": {
"node": ">=0.10.0"
"node": ">=4.0.0"
},
"scripts": {
"start": "rm -rf build/* && node server.js",
"build": "rm -rf build/* && ./node_modules/.bin/webpack",
"dist": "rm -rf dist/* && ./node_modules/.bin/webpack -p --config webpack.production.config.js",
"lint": "./node_modules/.bin/eslint src/",
"test": "./node_modules/.bin/karma start ./test/karma.conf.js",
"test-dev": "./node_modules/.bin/karma start ./test/karma.conf.js --no-single-run"
"test": "./node_modules/.bin/karma start ./test/karma.conf.js --reporters mocha,coverage",
"test:watch": "./node_modules/.bin/karma start ./test/karma.conf.js --no-single-run --reporters mocha"
}
}
16 changes: 6 additions & 10 deletions src/js/components/LoginLinks.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,11 @@
import React from 'react';
import Actions from '../actions/Actions';

const LoginLinks = React.createClass({
render() {
return (
<span className="login-links">
<a onClick={ () => Actions.showModal('login') }>Sign In</a>
<a onClick={ () => Actions.showModal('register') } className="register-link">Register</a>
</span>
);
}
});
const LoginLinks = () => (
<span className="login-links">
<a onClick={ () => Actions.showModal('login') }>Sign In</a>
<a onClick={ () => Actions.showModal('register') } className="register-link">Register</a>
</span>
);

export default LoginLinks;
9 changes: 8 additions & 1 deletion src/js/components/Modal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ import Icon from './Icon';
const Modal = React.createClass({

propTypes: {
hideModal: PropTypes.func,
hideModal: PropTypes.func.isRequired,
children: PropTypes.oneOfType([
PropTypes.array,
PropTypes.element
]).isRequired
},

getDefaultProps() {
return {
hideModal: () => {},
children: null
};
},

componentDidMount() {
// allow esc to close modal
document.addEventListener('keyup', this.onKeyUp);
Expand Down
81 changes: 81 additions & 0 deletions src/js/components/__tests__/Login-test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
'use strict';

import React from 'react';
import { findDOMNode } from 'react-dom';
import createParent from '../../../../test/util/createParent';
import Login from '../Login';

import {
createRenderer,
renderIntoDocument,
findRenderedDOMComponentWithTag
} from 'react-addons-test-utils';

const userData = {
username: 'echenley',
md5hash: '7da6a19ef0b1a9b9794cf5c7cc7439f1'
};

const errorMessage = 'uh oh';

const renderer = createRenderer();

describe('<Login />', () => {
describe('DOM', () => {
it('should render correctly WITH errorMessage prop', () => {
// login with errorMessage prop
renderer.render(<Login user={ userData } errorMessage={ errorMessage } />);
const actualElement = renderer.getRenderOutput();

const expectedErrorMessage = (
<div className="error modal-form-error">{ errorMessage }</div>
);

expect(actualElement).to.includeJSX(expectedErrorMessage);
});

it('should render correctly WITHOUT errorMessage prop', () => {
// login without errorMessage prop
renderer.render(<Login user={ userData } />);
const actualElement = renderer.getRenderOutput();
const actualErrorMessage = actualElement.props.children[2];

expect(actualErrorMessage).to.not.exist;
});
});

describe('Behavior', () => {
let parent;
let login;

beforeEach(() => {
let LoginParent = createParent(Login, 'login', {
errorMessage: '',
user: { isLoggedIn: false }
});

parent = renderIntoDocument(<LoginParent />);
login = parent.refs.login;
});

it('should disable submit button until props update', () => {
let submitButton = findDOMNode(findRenderedDOMComponentWithTag(login, 'button'));

login.setState({ submitted: true });
expect(submitButton.disabled).to.equal(true);

parent.setState({ errorMessage: 'invalid user' });

expect(login.state.submitted).to.equal(false);
expect(submitButton.disabled).to.equal(false);
});

it('should clear form when user prop updates', () => {
login.clearForm = sinon.spy();
expect(login.clearForm).to.have.not.been.called;

parent.setState({ user: { isLoggedIn: true } });
expect(login.clearForm).to.have.been.called;
});
});
});
25 changes: 25 additions & 0 deletions src/js/components/__tests__/LoginLinks-test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict';

import React from 'react';
import { createRenderer } from 'react-addons-test-utils';

import LoginLinks from '../LoginLinks';

describe('<LoginLinks />', () => {
describe('DOM', function() {
it('should render correctly', () => {
const renderer = createRenderer();
renderer.render(<LoginLinks />);
const actualElement = renderer.getRenderOutput();

const expectedElement = (
<span className="login-links">
<a onClick={ () => {} }>Sign In</a>
<a onClick={ () => {} } className="register-link">Register</a>
</span>
);

expect(actualElement).to.equalJSX(expectedElement);
});
});
});
86 changes: 86 additions & 0 deletions src/js/components/__tests__/Modal-test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
'use strict';

import React from 'react';
import { findDOMNode } from 'react-dom';
import createParent from '../../../../test/util/createParent';
import Modal from '../Modal';
import Icon from '../Icon';

import {
createRenderer,
renderIntoDocument,
findRenderedDOMComponentWithClass,
Simulate
} from 'react-addons-test-utils';


describe('<Modal />', () => {
describe('DOM', () => {
it('should render properly', () => {
const childJSX = (
<div className="modal-child">hey</div>
);

const shallowRenderer = createRenderer();
shallowRenderer.render(<Modal>{ childJSX }</Modal>);
const actualElement = shallowRenderer.getRenderOutput();

expect(actualElement).to.equalJSX((
<div className="modal-overlay" onClick={ () => {} }>
<div className="modal-inner" onClick={ () => {} }>
<a href="#" onClick={ () => {} } className="modal-close">
<Icon svg={ require('../../../svg/close.svg') } />
<span className="sr-only">Hide Modal</span>
</a>
{ childJSX }
</div>
</div>
));
});
});

describe('Behavior', () => {
let parent;
let modal;
let hideModalSpy;

beforeEach(() => {
hideModalSpy = sinon.spy();

let ModalParent = createParent(Modal, 'modal', {
hideModal: hideModalSpy,
children: <div />
});

parent = renderIntoDocument(<ModalParent />);
modal = parent.refs.modal;
});

it('should call props.hideModal when .modal-overlay is clicked', () => {
expect(hideModalSpy).to.have.not.been.called;
Simulate.click(findDOMNode(modal));
expect(hideModalSpy).to.have.been.called;
});

it('should call props.hideModal when .modal-close is clicked', () => {
const modalClose = findRenderedDOMComponentWithClass(modal, 'modal-close');
expect(hideModalSpy).to.have.not.been.called;
Simulate.click(findDOMNode(modalClose));
expect(hideModalSpy).to.have.been.called;
});

// TODO: figure out how to test this
// it('should call props.hideModal when escape key is pressed', () => {
// expect(hideModalSpy).to.have.not.been.called;
// Simulate.keyPress(document, { keyCode: 27 });
// expect(hideModalSpy).to.have.been.called;
// });

it('should not be removed when .modal-inner is clicked', () => {
const modalInner = findRenderedDOMComponentWithClass(modal, 'modal-inner');
expect(hideModalSpy).to.have.not.been.called;
Simulate.click(findDOMNode(modalInner));
expect(hideModalSpy).to.have.not.been.called;
});
});
});
31 changes: 31 additions & 0 deletions src/js/components/__tests__/ProfileLink-test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict';

import React from 'react';
import { createRenderer } from 'react-addons-test-utils';

import { Link } from 'react-router';
import ProfileLink from '../ProfileLink';

const userData = {
username: 'echenley',
md5hash: '7da6a19ef0b1a9b9794cf5c7cc7439f1'
};

const renderer = createRenderer();
renderer.render(<ProfileLink user={ userData } />);
const actualElement = renderer.getRenderOutput();

const expectedElement = (
<Link to={ `/user/${userData.username}` } className="profile-link">
<span className="username">{ userData.username }</span>
<img src={ `http://www.gravatar.com/avatar/${userData.md5hash}?d=mm` } className="profile-pic" />
</Link>
);

describe('<ProfileLink />', () => {
describe('DOM', function() {
it('should render correctly', () => {
expect(actualElement).to.equalJSX(expectedElement);
});
});
});
Loading

0 comments on commit e706d48

Please sign in to comment.