#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 "es6": true
}, },
"globals": {
"sinon": false // needed for tests. Apply it globaly till eslint/selint#3611
},
"extends": "eslint:recommended", "extends": "eslint:recommended",
// @see: http://eslint.org/docs/rules/ // @see: http://eslint.org/docs/rules/
@ -191,7 +187,8 @@
"require-yield": "error", "require-yield": "error",
// react // react
"react/display-name": "warn", "react/display-name": "off",
"react/react-in-jsx-scope": "warn",
"react/forbid-prop-types": "warn", "react/forbid-prop-types": "warn",
"react/jsx-boolean-value": "warn", "react/jsx-boolean-value": "warn",
"react/jsx-closing-bracket-location": "off", // can not configure for our code style "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-max-props-per-line": ["warn", {"maximum": 3}],
"react/jsx-no-bind": "off", "react/jsx-no-bind": "off",
"react/jsx-no-duplicate-props": "warn", "react/jsx-no-duplicate-props": "warn",
"react/jsx-no-literals": "warn", "react/jsx-no-literals": "off",
"react/jsx-no-undef": "error", "react/jsx-no-undef": "error",
"react/jsx-pascal-case": "warn", "react/jsx-pascal-case": "warn",
"react/jsx-uses-react": "warn", "react/jsx-uses-react": "warn",
@ -221,6 +218,6 @@
"react/prefer-es6-class": "warn", "react/prefer-es6-class": "warn",
"react/prop-types": "warn", "react/prop-types": "warn",
"react/self-closing-comp": "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 { Link } from 'react-router-dom';
import { FormattedMessage as Message } from 'react-intl'; import { FormattedMessage as Message } from 'react-intl';
@ -19,12 +20,12 @@ const rules = [
{ {
title: <Message {...messages.mainProvisions} />, title: <Message {...messages.mainProvisions} />,
items: [ items: [
<Message {...messages.mainProvision1} values={{ <Message key="0" {...messages.mainProvision1} values={{
name: (<b>{projectName}</b>) name: (<b>{projectName}</b>)
}} />, }} />,
<Message {...messages.mainProvision2} />, <Message key="1" {...messages.mainProvision2} />,
<Message {...messages.mainProvision3} />, <Message key="2" {...messages.mainProvision3} />,
<Message {...messages.mainProvision4} values={{ <Message key="3" {...messages.mainProvision4} values={{
link: (<Link to="/register">https://account.ely.by/register</Link>) link: (<Link to="/register">https://account.ely.by/register</Link>)
}} /> }} />
] ]
@ -32,13 +33,13 @@ const rules = [
{ {
title: <Message {...messages.emailAndNickname} />, title: <Message {...messages.emailAndNickname} />,
items: [ items: [
<Message {...messages.emailAndNickname1} />, <Message key="0" {...messages.emailAndNickname1} />,
<Message {...messages.emailAndNickname2} />, <Message key="1" {...messages.emailAndNickname2} />,
<Message {...messages.emailAndNickname3} />, <Message key="2" {...messages.emailAndNickname3} />,
<Message {...messages.emailAndNickname4} />, <Message key="3" {...messages.emailAndNickname4} />,
<Message {...messages.emailAndNickname5} />, <Message key="4" {...messages.emailAndNickname5} />,
<Message {...messages.emailAndNickname6} />, <Message key="5" {...messages.emailAndNickname6} />,
<Message {...messages.emailAndNickname7} /> <Message key="6" {...messages.emailAndNickname7} />
] ]
}, },
{ {
@ -52,22 +53,23 @@ const rules = [
<p><Message {...messages.elyAccountsAsServiceDesc2} /></p> <p><Message {...messages.elyAccountsAsServiceDesc2} /></p>
</div>), </div>),
items: [ items: [
<Message {...messages.elyAccountsAsService1} />, <Message key="0" {...messages.elyAccountsAsService1} />,
<Message {...messages.elyAccountsAsService2} /> <Message key="1" {...messages.elyAccountsAsService2} />
] ]
} }
]; ];
export default class RulesPage extends Component { export default class RulesPage extends Component {
static propTypes = { props: {
location: PropTypes.shape({ location: {
pathname: PropTypes.string, pathname: string,
search: PropTypes.string, search: string,
hash: PropTypes.string hash: string
}).isRequired, },
history: PropTypes.shape({
replace: PropTypes.func history: {
}).isRequired replace: Function
}
}; };
render() { render() {
@ -128,8 +130,11 @@ export default class RulesPage extends Component {
); );
} }
onRuleClick(event) { onRuleClick(event: MouseEvent & {target: HTMLElement, currentTarget: HTMLElement}) {
if (event.defaultPrevented || event.target.tagName.toLowerCase() === 'a') { if (event.defaultPrevented
|| !event.currentTarget.id
|| event.target.tagName.toLowerCase() === 'a'
) {
// some-one have already processed this event or it is a link // some-one have already processed this event or it is a link
return; return;
} }
@ -148,5 +153,3 @@ export default class RulesPage extends Component {
return `${RulesPage.getTitleHash(sectionIndex)}-${ruleIndex + 1}`; 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');
});
});
});