From a90645a95f11596b22a7cbe8c08f2594b0d9bee2 Mon Sep 17 00:00:00 2001 From: Mike Stone Date: Tue, 6 Sep 2016 14:41:16 -0400 Subject: [PATCH] Testing/linting setup (#120) --- .eslintignore | 12 ++++++ .eslintrc.js | 38 +++++++++++++++++++ Makefile | 1 + .../components/app/{index.js => index.jsx} | 1 - frontend/components/app/index.tests.jsx | 16 ++++++++ frontend/css/funcs.js | 6 +-- frontend/css/index.js | 4 +- frontend/css/vars.js | 4 +- frontend/index.js | 4 +- frontend/router/{index.js => index.jsx} | 25 ++++++------ package.json | 20 +++++++++- testSetup.js | 7 ++++ 12 files changed, 116 insertions(+), 22 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.js rename frontend/components/app/{index.js => index.jsx} (87%) create mode 100644 frontend/components/app/index.tests.jsx rename frontend/router/{index.js => index.jsx} (53%) create mode 100644 testSetup.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..7e575918d --- /dev/null +++ b/.eslintignore @@ -0,0 +1,12 @@ +.vscode +build +cli +config +datastore +errors +kolide +mock +server +tools +vendor +webpack.config.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..5193d635e --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,38 @@ +var path = require('path'); + +module.exports = { + extends: "airbnb", + parser: "babel-eslint", + plugins: [ + "react" + ], + env: { + "node": true, + "mocha": true + }, + globals: { + "expect": false, + "describe": false + }, + rules: { + "consistent-return": 1, + "arrow-body-style": 0, + "max-len": 0, + "no-use-before-define": [2, "nofunc"], + "no-unused-expressions": 0, + "no-console": 0, + "space-before-function-paren": 0, + "react/prefer-stateless-function": 0, + "react/no-multi-comp": 0, + "no-param-reassign": 0, + "new-cap": 0, + 'import/no-unresolved': 'error' + }, + settings: { + 'import/resolver': { + webpack: { + config: path.join(__dirname, 'webpack.config.js') + } + } + } +} diff --git a/Makefile b/Makefile index e812ae356..0ec33e231 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ endif test: go vet $(shell glide nv) go test -v -cover $(shell glide nv) + npm run test generate: .prefix go-bindata -pkg=server -o=server/bindata.go frontend/templates/ build/ diff --git a/frontend/components/app/index.js b/frontend/components/app/index.jsx similarity index 87% rename from frontend/components/app/index.js rename to frontend/components/app/index.jsx index 75ca455c9..a469eeb40 100644 --- a/frontend/components/app/index.js +++ b/frontend/components/app/index.jsx @@ -1,5 +1,4 @@ import React, { Component } from 'react'; -import '#components/app/styles.css'; class App extends Component { render() { diff --git a/frontend/components/app/index.tests.jsx b/frontend/components/app/index.tests.jsx new file mode 100644 index 000000000..c8656e432 --- /dev/null +++ b/frontend/components/app/index.tests.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import expect from 'expect'; +import { mount } from 'enzyme'; +import App from './index'; + +describe('App', () => { + const component = mount(); + + it('renders', () => { + expect(component).toExist(); + }); + + it('renders the appropriate text', () => { + expect(component.text()).toInclude('If you can read this, React is rendering correctly!'); + }); +}); diff --git a/frontend/css/funcs.js b/frontend/css/funcs.js index 8091b5b1c..e33af3f9e 100644 --- a/frontend/css/funcs.js +++ b/frontend/css/funcs.js @@ -10,7 +10,7 @@ module.exports = { * // returns "height: 5px;" height: px(5); */ - px: function(val) { - return val + 'px'; - } + px: (val) => { + return `${val}px`; + }, }; diff --git a/frontend/css/index.js b/frontend/css/index.js index bdafdedc8..eddb81b30 100644 --- a/frontend/css/index.js +++ b/frontend/css/index.js @@ -1,5 +1,5 @@ require('normalize.css'); -require('#css/global'); +require('./global.css'); /** * Components. @@ -7,4 +7,4 @@ require('#css/global'); * to hot reload it. And make sure that you * use `webpack.optimize.DedupePlugin` */ -require('#app/components/app/styles'); +require('../components/app/styles.css'); diff --git a/frontend/css/vars.js b/frontend/css/vars.js index da039ecf0..52be571cd 100644 --- a/frontend/css/vars.js +++ b/frontend/css/vars.js @@ -2,6 +2,6 @@ * Global CSS Variables. * @module css/vars */ -module.exports = { - mainColor: '#333' +export default { + mainColor: '#333', }; diff --git a/frontend/index.js b/frontend/index.js index 61aac81ca..49b8ad928 100644 --- a/frontend/index.js +++ b/frontend/index.js @@ -1,5 +1,5 @@ -const router = require('#app/router'); +import { run } from './router'; if (typeof window !== 'undefined') { - router.run(); + run(); } diff --git a/frontend/router/index.js b/frontend/router/index.jsx similarity index 53% rename from frontend/router/index.js rename to frontend/router/index.jsx index 6ca496753..d905d1d4d 100644 --- a/frontend/router/index.js +++ b/frontend/router/index.jsx @@ -1,32 +1,35 @@ import React from 'react'; import { render } from 'react-dom'; -import { Router, Route, IndexRoute, browserHistory } from 'react-router'; +import { Router, Route, browserHistory } from 'react-router'; import { Promise } from 'when'; -import App from '#components/app'; +import App from '../components/app'; + +const window = global.window || {}; +const document = global.document || {}; export function run() { window.Promise = window.Promise || Promise; window.self = window; - require('whatwg-fetch'); - render(( - - - -), document.getElementById('app')) + const router = ( + + + + ); + render(router, document.getElementById('app')); } -require('#css'); // Style live reloading if (module.hot) { let c = 0; module.hot.accept('#css', () => { - require('#css'); const a = document.createElement('a'); const link = document.querySelector('link[rel="stylesheet"]'); a.href = link.href; - a.search = '?' + c++; + a.search = `?${c++}`; link.href = a.href; }); } + +export default { run }; diff --git a/package.json b/package.json index b30d8fbd8..023dc575f 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,11 @@ "description": "Kolide, Black Box Security. Unboxed", "author": "Kolide, Inc.", "private": "true", + "scripts": { + "lint": "eslint . --ext .js,.jsx", + "mocha": "node_modules/mocha/bin/_mocha --compilers js:babel-core/register --recursive 'frontend/**/*.tests.js*' --require testSetup.js", + "test": "npm run lint && npm run mocha" + }, "dependencies": { "autoprefixer": "6.3.7", "autoprefixer-loader": "^3.2.0", @@ -17,13 +22,15 @@ "babel-preset-stage-0": "6.5.0", "css-loader": "^0.23.1", "cssrecipes-defaults": "^0.5.0", + "enzyme": "^2.4.1", "es6-promise": "^3.2.1", - "eslint-plugin-react": "^3.16.1", + "expect": "^1.20.2", "expose-loader": "^0.7.1", "express": "^4.13.4", "extract-text-webpack-plugin": "^1.0.1", "file-loader": "^0.8.5", "history": "2.0.0", + "jsdom": "^9.5.0", "lodash": "^4.3.0", "normalize.css": "4.2.0", "postcss-functions": "^2.1.0", @@ -89,5 +96,16 @@ "plugins": [ "react" ] + }, + "devDependencies": { + "babel-eslint": "^6.1.2", + "eslint": "^3.4.0", + "eslint-config-airbnb": "^10.0.1", + "eslint-plugin-import": "^1.14.0", + "eslint-plugin-jsx-a11y": "^2.1.1", + "eslint-plugin-react": "^6.0.0", + "mocha": "^3.0.2", + "react-addons-test-utils": "^15.3.1", + "react-dom": "^15.3.1" } } diff --git a/testSetup.js b/testSetup.js new file mode 100644 index 000000000..bf9a6dec6 --- /dev/null +++ b/testSetup.js @@ -0,0 +1,7 @@ +import jsdom from 'jsdom'; + +const doc = jsdom.jsdom(''); + +global.document = doc; +global.window = doc.defaultView; +global.navigator = global.window.navigator;