#85: tests for rules page

This commit is contained in:
SleepWalker 2017-06-07 23:09:11 +03:00
parent 3d3f50049e
commit 7c4d735c80
3 changed files with 119 additions and 34 deletions

View File

@ -35,10 +35,6 @@
"es6": true
},
"globals": {
"sinon": false // needed for tests. Apply it globaly till eslint/selint#3611
},
"extends": "eslint:recommended",
// @see: http://eslint.org/docs/rules/
@ -191,7 +187,8 @@
"require-yield": "error",
// react
"react/display-name": "warn",
"react/display-name": "off",
"react/react-in-jsx-scope": "warn",
"react/forbid-prop-types": "warn",
"react/jsx-boolean-value": "warn",
"react/jsx-closing-bracket-location": "off", // can not configure for our code style
@ -202,7 +199,7 @@
"react/jsx-max-props-per-line": ["warn", {"maximum": 3}],
"react/jsx-no-bind": "off",
"react/jsx-no-duplicate-props": "warn",
"react/jsx-no-literals": "warn",
"react/jsx-no-literals": "off",
"react/jsx-no-undef": "error",
"react/jsx-pascal-case": "warn",
"react/jsx-uses-react": "warn",
@ -221,6 +218,6 @@
"react/prefer-es6-class": "warn",
"react/prop-types": "warn",
"react/self-closing-comp": "warn",
"react/sort-comp": ["warn", {"order": ["lifecycle", "render", "everything-else"]}]
"react/sort-comp": ["off", {"order": ["lifecycle", "render", "everything-else"]}]
}
}

View File

@ -1,4 +1,5 @@
import React, { Component, PropTypes } from 'react';
// @flow
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { FormattedMessage as Message } from 'react-intl';
@ -19,12 +20,12 @@ const rules = [
{
title: <Message {...messages.mainProvisions} />,
items: [
<Message {...messages.mainProvision1} values={{
<Message key="0" {...messages.mainProvision1} values={{
name: (<b>{projectName}</b>)
}} />,
<Message {...messages.mainProvision2} />,
<Message {...messages.mainProvision3} />,
<Message {...messages.mainProvision4} values={{
<Message key="1" {...messages.mainProvision2} />,
<Message key="2" {...messages.mainProvision3} />,
<Message key="3" {...messages.mainProvision4} values={{
link: (<Link to="/register">https://account.ely.by/register</Link>)
}} />
]
@ -32,13 +33,13 @@ const rules = [
{
title: <Message {...messages.emailAndNickname} />,
items: [
<Message {...messages.emailAndNickname1} />,
<Message {...messages.emailAndNickname2} />,
<Message {...messages.emailAndNickname3} />,
<Message {...messages.emailAndNickname4} />,
<Message {...messages.emailAndNickname5} />,
<Message {...messages.emailAndNickname6} />,
<Message {...messages.emailAndNickname7} />
<Message key="0" {...messages.emailAndNickname1} />,
<Message key="1" {...messages.emailAndNickname2} />,
<Message key="2" {...messages.emailAndNickname3} />,
<Message key="3" {...messages.emailAndNickname4} />,
<Message key="4" {...messages.emailAndNickname5} />,
<Message key="5" {...messages.emailAndNickname6} />,
<Message key="6" {...messages.emailAndNickname7} />
]
},
{
@ -52,22 +53,23 @@ const rules = [
<p><Message {...messages.elyAccountsAsServiceDesc2} /></p>
</div>),
items: [
<Message {...messages.elyAccountsAsService1} />,
<Message {...messages.elyAccountsAsService2} />
<Message key="0" {...messages.elyAccountsAsService1} />,
<Message key="1" {...messages.elyAccountsAsService2} />
]
}
];
export default class RulesPage extends Component {
static propTypes = {
location: PropTypes.shape({
pathname: PropTypes.string,
search: PropTypes.string,
hash: PropTypes.string
}).isRequired,
history: PropTypes.shape({
replace: PropTypes.func
}).isRequired
props: {
location: {
pathname: string,
search: string,
hash: string
},
history: {
replace: Function
}
};
render() {
@ -128,8 +130,11 @@ export default class RulesPage extends Component {
);
}
onRuleClick(event) {
if (event.defaultPrevented || event.target.tagName.toLowerCase() === 'a') {
onRuleClick(event: MouseEvent & {target: HTMLElement, currentTarget: HTMLElement}) {
if (event.defaultPrevented
|| !event.currentTarget.id
|| event.target.tagName.toLowerCase() === 'a'
) {
// some-one have already processed this event or it is a link
return;
}
@ -148,5 +153,3 @@ export default class RulesPage extends Component {
return `${RulesPage.getTitleHash(sectionIndex)}-${ruleIndex + 1}`;
}
}
RulesPage.displayName = 'RulesPage';

View File

@ -0,0 +1,85 @@
import React from 'react';
import sinon from 'sinon';
import expect from 'unexpected';
import {shallow} from 'enzyme';
import RulesPage from './RulesPage';
describe('RulesPage', () => {
describe('#onRuleClick()', () => {
const id = 'rule-1-2';
const pathname = '/foo';
const search = '?bar';
let page;
let replace;
beforeEach(() => {
replace = sinon.stub().named('history.replace');
page = shallow(<RulesPage
location={{pathname, search}}
history={{replace}}
/>);
});
it('should update location on rule click', () => {
const expectedUrl = `/foo?bar#${id}`;
page.find(`#${id}`).simulate('click', {
target: {
tagName: 'li'
},
currentTarget: {
id
}
});
expect(replace, 'to have a call satisfying', [expectedUrl]);
});
it('should not update location if link was clicked', () => {
page.find(`#${id}`).simulate('click', {
target: {
tagName: 'a'
},
currentTarget: {
id
}
});
expect(replace, 'was not called');
});
it('should not update location if defaultPrevented', () => {
page.find(`#${id}`).simulate('click', {
defaultPrevented: true,
target: {
tagName: 'li'
},
currentTarget: {
id
}
});
expect(replace, 'was not called');
});
it('should not update location if no id', () => {
page.find(`#${id}`).simulate('click', {
target: {
tagName: 'li'
},
currentTarget: {
}
});
expect(replace, 'was not called');
});
});
});