diff options
author | Anike Arni <anikarni@gmail.com> | 2017-02-08 17:45:34 -0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-08 17:45:34 -0200 |
commit | 0d4cf4ad3a5da62f65730d6c3e3665fc12d72590 (patch) | |
tree | e852ab83caeca6158ffc78e3cda100157ddb9f88 /web-ui | |
parent | a1c384cebd80e177389ef79c2de6400db986aaa6 (diff) | |
parent | ea852b12e33b0e50ba7986c33ad68be5e38305ba (diff) |
Merge pull request #965 from pixelated/backup-email-page
Adds lint, coverage and css autoprefixer
Diffstat (limited to 'web-ui')
-rw-r--r-- | web-ui/.babelrc | 7 | ||||
-rw-r--r-- | web-ui/.eslintrc.json | 18 | ||||
-rw-r--r-- | web-ui/config/loaders-webpack.js | 2 | ||||
-rw-r--r-- | web-ui/package.json | 53 | ||||
-rw-r--r-- | web-ui/postcss.config.js | 5 | ||||
-rw-r--r-- | web-ui/src/account_recovery/account_recovery.js | 20 | ||||
-rw-r--r-- | web-ui/src/account_recovery/page.js | 22 | ||||
-rw-r--r-- | web-ui/src/account_recovery/page.scss | 11 | ||||
-rw-r--r-- | web-ui/src/common/input_field/input-field.scss | 4 | ||||
-rw-r--r-- | web-ui/src/common/input_field/input_field.js | 13 | ||||
-rw-r--r-- | web-ui/src/common/submit_button/submit-button.scss | 2 | ||||
-rw-r--r-- | web-ui/src/common/submit_button/submit_button.js | 12 | ||||
-rw-r--r-- | web-ui/src/i18n.js | 12 | ||||
-rw-r--r-- | web-ui/test/unit/account_recovery/page.spec.js | 31 | ||||
-rw-r--r-- | web-ui/test/unit/common/input_field/input_field.spec.js | 20 | ||||
-rw-r--r-- | web-ui/test/unit/common/submit_button/submit_button.spec.js | 16 | ||||
-rw-r--r-- | web-ui/webpack.config.js | 1 |
17 files changed, 164 insertions, 85 deletions
diff --git a/web-ui/.babelrc b/web-ui/.babelrc index 86c445f5..e74e4d82 100644 --- a/web-ui/.babelrc +++ b/web-ui/.babelrc @@ -1,3 +1,8 @@ { - "presets": ["es2015", "react"] + "presets": ["es2015", "react"], + "env": { + "test": { + "plugins": ["istanbul"] + } + } } diff --git a/web-ui/.eslintrc.json b/web-ui/.eslintrc.json new file mode 100644 index 00000000..554498f9 --- /dev/null +++ b/web-ui/.eslintrc.json @@ -0,0 +1,18 @@ +/* see https://github.com/airbnb/javascript for lint rules */ +{ + "extends": "airbnb", + "plugins": [ + "react", + "jsx-a11y", + "import" + ], + "rules": { + "import/no-extraneous-dependencies": ["off"], + "import/extensions": ["off"], + "import/no-unresolved": ["off"], + "react/jsx-filename-extension": ["off"], + "jsx-quotes": ["error", "prefer-single"], + "no-undef": ["off"], + "comma-dangle": ["off"] + } +} diff --git a/web-ui/config/loaders-webpack.js b/web-ui/config/loaders-webpack.js index 21e9a572..f5237dff 100644 --- a/web-ui/config/loaders-webpack.js +++ b/web-ui/config/loaders-webpack.js @@ -7,7 +7,7 @@ module.exports = [ }, { test: /\.scss|css$/, - loader: "style-loader!css-loader!sass-loader" + loader: "style-loader!css-loader!postcss-loader!sass-loader" }, { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, diff --git a/web-ui/package.json b/web-ui/package.json index dba34e97..4f7c1bc5 100644 --- a/web-ui/package.json +++ b/web-ui/package.json @@ -9,6 +9,7 @@ "babel-cli": "^6.22.2", "babel-core": "^6.21.0", "babel-loader": "^6.2.10", + "babel-plugin-istanbul": "^3.1.2", "babel-preset-es2015": "^6.18.0", "babel-preset-react": "^6.22.0", "bower": "1.7.9", @@ -16,6 +17,11 @@ "css-loader": "^0.26.1", "dompurify": "^0.8.4", "enzyme": "^2.7.1", + "eslint": "^3.15.0", + "eslint-config-airbnb": "^14.1.0", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-jsx-a11y": "^4.0.0", + "eslint-plugin-react": "^6.9.0", "expect": "^1.20.2", "file-loader": "^0.10.0", "font-awesome": "^4.7.0", @@ -48,6 +54,8 @@ "mocha-webpack": "^0.7.0", "modernizr": "^3.3.1", "node-sass": "^4.5.0", + "nyc": "^10.1.2", + "postcss-loader": "^1.2.2", "quoted-printable": "^1.0.1", "react": "^15.4.2", "react-a11y": "^0.3.3", @@ -64,26 +72,35 @@ "webpack": "^1.14.0" }, "scripts": { - "test": "npm run jshint --silent && npm run build-statics --silent && npm run mocha-test && npm run karma-test", - "mocha-test": "mocha-webpack --webpack-config webpack.test.config.js \"test/unit/**/*.spec.js\"", - "mocha-watch": "mocha-webpack --watch --webpack-config webpack.test.config.js \"test/unit/**/*.spec.js\"", - "karma-test": "karma start --single-run $GRUNT_OPTS", - "debug": "npm run build && karma start --browsers Chrome $GRUNT_OPTS", - "watch": "npm run compass-watch & npm run handlebars-watch & npm run build-js-watch", - "watch-test": "karma start", - "handlebars": "mkdir -p app/js/generated/hbs/ && handlebars app/templates/**/*.hbs > app/js/generated/hbs/templates.js --namespace=window.Pixelated --root .", - "handlebars-watch": "watch 'npm run handlebars' app/templates", - "compass": "compass compile", - "compass-watch": "compass watch", - "build": "npm run build-statics && npm run build-js", - "build-statics": "npm run clean && npm run handlebars && npm run add_git_version && npm run compass", - "build-prod": "npm run build-statics && webpack -p --config ./webpack.production.config.js", - "build-js": "webpack --colors --progress", - "build-js-watch": "webpack --colors --progress --watch", - "jshint": "jshint --config=.jshintrc app test", + "test": "npm run lint --silent && npm run build:statics --silent && npm run test:unit", + "test:unit": "npm run test:coverage && npm run test:karma", + "test:coverage": "NODE_ENV=test nyc --check-coverage npm run test:mocha", + "test:mocha": "mocha-webpack --webpack-config webpack.test.config.js \"test/unit/**/*.spec.js\"", + "test:karma": "karma start --single-run $GRUNT_OPTS", + "test:watch:mocha": "npm run test:mocha -- --watch", + "test:watch:karma": "karma start", + "lint": "npm run lint:jshint && npm run lint:eslint", + "lint:jshint": "jshint --config=.jshintrc app test", + "lint:eslint": "eslint src test/unit", + "build": "npm run build:statics && npm run build:js", + "build:debug": "npm run build && karma start --browsers Chrome $GRUNT_OPTS", + "build:statics": "npm run clean && npm run build:handlebars && npm run add_git_version && npm run build:compass", + "build:prod": "npm run build:statics && webpack -p --config ./webpack.production.config.js", + "build:js": "webpack --colors --progress", + "build:compass": "compass compile", + "build:handlebars": "mkdir -p app/js/generated/hbs/ && handlebars app/templates/**/*.hbs > app/js/generated/hbs/templates.js --namespace=window.Pixelated --root .", + "watch": "npm run watch:compass & npm run watch:handlebars & npm run watch:js", + "watch:handlebars": "watch 'npm run build:handlebars' app/templates", + "watch:compass": "compass watch", + "watch:js": "webpack --colors --progress --watch", "clean": "rm -rf dist/ app/js/generated/hbs/* app/css/*", - "package": "PIXELATED_BUILD='package' npm run build-prod && npm run imagemin", "imagemin": "node config/imagemin.js", + "package": "PIXELATED_BUILD='package' npm run build:prod && npm run imagemin", "add_git_version": "/bin/bash config/add_git_version.sh" + }, + "nyc": { + "include": [ + "src/**/*.js" + ] } } diff --git a/web-ui/postcss.config.js b/web-ui/postcss.config.js new file mode 100644 index 00000000..88752c6c --- /dev/null +++ b/web-ui/postcss.config.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: [ + require('autoprefixer') + ] +} diff --git a/web-ui/src/account_recovery/account_recovery.js b/web-ui/src/account_recovery/account_recovery.js index 6c12e326..d4e0f4e8 100644 --- a/web-ui/src/account_recovery/account_recovery.js +++ b/web-ui/src/account_recovery/account_recovery.js @@ -15,21 +15,21 @@ * along with Pixelated. If not, see <http://www.gnu.org/licenses/>. */ -import React from 'react' -import { render } from 'react-dom' -import a11y from 'react-a11y' -import { I18nextProvider } from 'react-i18next' +import React from 'react'; +import { render } from 'react-dom'; +import a11y from 'react-a11y'; +import { I18nextProvider } from 'react-i18next'; -import Page from './page' -import i18n from '../i18n' +import 'font-awesome/scss/font-awesome.scss'; -import 'font-awesome/scss/font-awesome.scss' +import PageWrapper from './page'; +import i18n from '../i18n'; -if(process.env.NODE_ENV === 'development') a11y(React); +if (process.env.NODE_ENV === 'development') a11y(React); render( - <I18nextProvider i18n={ i18n }> - <Page/> + <I18nextProvider i18n={i18n}> + <PageWrapper /> </I18nextProvider>, document.getElementById('root') ); diff --git a/web-ui/src/account_recovery/page.js b/web-ui/src/account_recovery/page.js index d1bcb464..ac01529d 100644 --- a/web-ui/src/account_recovery/page.js +++ b/web-ui/src/account_recovery/page.js @@ -15,12 +15,12 @@ * along with Pixelated. If not, see <http://www.gnu.org/licenses/>. */ -import React from 'react' -import { translate } from 'react-i18next' -import SubmitButton from 'src/common/submit_button/submit_button' -import InputField from 'src/common/input_field/input_field' +import React from 'react'; +import { translate } from 'react-i18next'; +import SubmitButton from 'src/common/submit_button/submit_button'; +import InputField from 'src/common/input_field/input_field'; -import './page.scss' +import './page.scss'; export const Page = ({ t }) => ( <div className='container'> @@ -32,13 +32,17 @@ export const Page = ({ t }) => ( <InputField name='email' label={t('backup-account.input-label')} /> <SubmitButton buttonText={t('backup-account.button')} /> <div> - <a href="/"> - <i className="fa fa-angle-left" aria-hidden="true"></i> + <a href='/'> + <i className='fa fa-angle-left' aria-hidden='true' /> <span>{t('back-to-inbox')}</span> </a> </div> </form> </div> -) +); -export default translate('', { wait: true })(Page) +Page.propTypes = { + t: React.PropTypes.func.isRequired +}; + +export default translate('', { wait: true })(Page); diff --git a/web-ui/src/account_recovery/page.scss b/web-ui/src/account_recovery/page.scss index c928d815..619d1105 100644 --- a/web-ui/src/account_recovery/page.scss +++ b/web-ui/src/account_recovery/page.scss @@ -65,18 +65,13 @@ a { width: 84%; margin: 3% auto; padding: 6% 5%; - - -webkit-display: flex; display: flex; - -webkit-align-items: flex-start; align-items: flex-start; - -webkit-flex-direction: column; flex-direction: column; } img { width: 50%; - -webkit-align-self: center; align-self: center; } @@ -87,13 +82,10 @@ img { form { display: flex; - -webkit-display: flex; - -webkit-flex-direction: column; flex-direction: column; div { width: 70%; - -webkit-align-self: center; align-self: center; } } @@ -103,9 +95,7 @@ img { .container{ width: 60%; padding: 3%; - -webkit-align-items: flex-start; align-items: flex-start; - -webkit-flex-direction: row; flex-direction: row; max-width: 700px; } @@ -115,7 +105,6 @@ img { div { width: 300px; - -webkit-align-self: flex-start; align-self: flex-start; } } diff --git a/web-ui/src/common/input_field/input-field.scss b/web-ui/src/common/input_field/input-field.scss index 6ec827ab..dd8e8927 100644 --- a/web-ui/src/common/input_field/input-field.scss +++ b/web-ui/src/common/input_field/input-field.scss @@ -33,8 +33,6 @@ left: 6px; top:10px; transition:0.2s ease all; - -moz-transition:0.2s ease all; - -webkit-transition:0.2s ease all; } .input-field { @@ -61,7 +59,6 @@ @media only screen and (min-width : 500px) { .input-field-group { width: 70%; - -webkit-align-self: center; align-self: center; } } @@ -69,7 +66,6 @@ @media only screen and (min-width : 960px) { .input-field-group { width: 300px; - -webkit-align-self: flex-start; align-self: flex-start; margin-top: 3em; font-size: 1em; diff --git a/web-ui/src/common/input_field/input_field.js b/web-ui/src/common/input_field/input_field.js index 43899419..1378ba74 100644 --- a/web-ui/src/common/input_field/input_field.js +++ b/web-ui/src/common/input_field/input_field.js @@ -15,15 +15,20 @@ * along with Pixelated. If not, see <http://www.gnu.org/licenses/>. */ -import React from 'react' +import React from 'react'; -import './input-field.scss' +import './input-field.scss'; const InputField = ({ label, name }) => ( <div className='input-field-group'> <input type='text' name={name} className='input-field' required /> <label className='input-field-label' htmlFor={name}>{label}</label> </div> -) +); -export default InputField +InputField.propTypes = { + label: React.PropTypes.string.isRequired, + name: React.PropTypes.string.isRequired +}; + +export default InputField; diff --git a/web-ui/src/common/submit_button/submit-button.scss b/web-ui/src/common/submit_button/submit-button.scss index ccd0bef4..13cb7607 100644 --- a/web-ui/src/common/submit_button/submit-button.scss +++ b/web-ui/src/common/submit_button/submit-button.scss @@ -32,7 +32,6 @@ @media only screen and (min-width : 500px) { .submit-button { width: 70%; - -webkit-align-self: center; align-self: center; } } @@ -40,7 +39,6 @@ @media only screen and (min-width : 960px) { .submit-button { width: 300px; - -webkit-align-self: flex-start; align-self: flex-start; font-size: 0.8em; margin-bottom: 1em; diff --git a/web-ui/src/common/submit_button/submit_button.js b/web-ui/src/common/submit_button/submit_button.js index 89cfc55b..fb87bf7d 100644 --- a/web-ui/src/common/submit_button/submit_button.js +++ b/web-ui/src/common/submit_button/submit_button.js @@ -15,12 +15,16 @@ * along with Pixelated. If not, see <http://www.gnu.org/licenses/>. */ -import React from 'react' +import React from 'react'; -import './submit-button.scss' +import './submit-button.scss'; const SubmitButton = ({ buttonText }) => ( <input type='submit' className='submit-button' value={buttonText} /> -) +); -export default SubmitButton +SubmitButton.propTypes = { + buttonText: React.PropTypes.string.isRequired +}; + +export default SubmitButton; diff --git a/web-ui/src/i18n.js b/web-ui/src/i18n.js index 9c6ad550..bbbe2dcd 100644 --- a/web-ui/src/i18n.js +++ b/web-ui/src/i18n.js @@ -14,15 +14,15 @@ * You should have received a copy of the GNU Affero General Public License * along with Pixelated. If not, see <http://www.gnu.org/licenses/>. */ -import i18n from 'i18next' -import i18nBackend from 'i18nextXHRBackend' -import i18nDetector from 'i18nextBrowserLanguageDetector' +import i18n from 'i18next'; +import i18nBackend from 'i18nextXHRBackend'; +import I18nDetector from 'i18nextBrowserLanguageDetector'; -const detector = new i18nDetector(); +const detector = new I18nDetector(); const detect = detector.detect.bind(detector); -detector.detect = function(detectionOrder) { - let result = detect(detectionOrder); +detector.detect = (detectionOrder) => { + const result = detect(detectionOrder); return result.replace('-', '_'); }; diff --git a/web-ui/test/unit/account_recovery/page.spec.js b/web-ui/test/unit/account_recovery/page.spec.js index 590d1de8..6a139167 100644 --- a/web-ui/test/unit/account_recovery/page.spec.js +++ b/web-ui/test/unit/account_recovery/page.spec.js @@ -1,25 +1,26 @@ -import { shallow } from 'enzyme' -import expect from 'expect' -import React from 'react' -import { Page } from 'src/account_recovery/page' +import { shallow } from 'enzyme'; +import expect from 'expect'; +import React from 'react'; +import { Page } from 'src/account_recovery/page'; describe('Page', () => { - let mockT, page + let mockT; + let page; beforeEach(() => { - mockT = (key) => (key) - page = shallow(<Page t={mockT}/>) - }) + mockT = key => key; + page = shallow(<Page t={mockT} />); + }); it('renders backup email page title', () => { - expect(page.find('h1').text()).toEqual('backup-account.title') - }) + expect(page.find('h1').text()).toEqual('backup-account.title'); + }); it('renders backup account email input field', () => { - expect(page.find('InputField').props().name).toEqual('email') - }) + expect(page.find('InputField').props().name).toEqual('email'); + }); it('renders backup account submit button', () => { - expect(page.find('SubmitButton').props().buttonText).toEqual('backup-account.button') - }) -}) + expect(page.find('SubmitButton').props().buttonText).toEqual('backup-account.button'); + }); +}); diff --git a/web-ui/test/unit/common/input_field/input_field.spec.js b/web-ui/test/unit/common/input_field/input_field.spec.js new file mode 100644 index 00000000..0c044ce1 --- /dev/null +++ b/web-ui/test/unit/common/input_field/input_field.spec.js @@ -0,0 +1,20 @@ +import { shallow } from 'enzyme'; +import expect from 'expect'; +import React from 'react'; +import InputField from 'src/common/input_field/input_field'; + +describe('InputField', () => { + let inputField; + + beforeEach(() => { + inputField = shallow(<InputField label='Email' name='email' />); + }); + + it('renders an input of type text for email', () => { + expect(inputField.find('input[type="text"]').props().name).toEqual('email'); + }); + + it('renders a label for the email', () => { + expect(inputField.find('label').text()).toEqual('Email'); + }); +}); diff --git a/web-ui/test/unit/common/submit_button/submit_button.spec.js b/web-ui/test/unit/common/submit_button/submit_button.spec.js new file mode 100644 index 00000000..8279547c --- /dev/null +++ b/web-ui/test/unit/common/submit_button/submit_button.spec.js @@ -0,0 +1,16 @@ +import { shallow } from 'enzyme'; +import expect from 'expect'; +import React from 'react'; +import SubmitButton from 'src/common/submit_button/submit_button'; + +describe('SubmitButton', () => { + let submitButton; + + beforeEach(() => { + submitButton = shallow(<SubmitButton buttonText='Add Email' />); + }); + + it('renders an input of type submit for add email', () => { + expect(submitButton.find('input[type="submit"]').props().value).toEqual('Add Email'); + }); +}); diff --git a/web-ui/webpack.config.js b/web-ui/webpack.config.js index 9171b8f5..8a54af21 100644 --- a/web-ui/webpack.config.js +++ b/web-ui/webpack.config.js @@ -16,6 +16,7 @@ module.exports = { filename: '[name].js', publicPath: '/assets/' }, + devtool: 'source-map', resolve: { alias: aliases, extensions: ['', '.js'] |