From dac72dcc3f6c932a5b0a4597f8382caf1455404a Mon Sep 17 00:00:00 2001 From: Danilo Woznica Date: Fri, 20 Jan 2017 13:30:04 -0200 Subject: [PATCH] add react-npm-boilerplate --- .babelrc | 3 +++ .eslintrc | 51 +++++++++++++++++++++++++++++++++++ .gitignore | 9 +++++++ .npmignore | 10 +++++++ LICENSE | 21 +++++++++++++++ README.md | 29 +++++++++++++++++++- index.html | 2 ++ index.js | 1 + package.json | 60 +++++++++++++++++++++++++++++++++++++++++ scripts/mocha_runner.js | 21 +++++++++++++++ src/__tests__/index.js | 60 +++++++++++++++++++++++++++++++++++++++++ src/index.js | 23 ++++++++++++++++ 12 files changed, 289 insertions(+), 1 deletion(-) create mode 100755 .babelrc create mode 100755 .eslintrc create mode 100755 .gitignore create mode 100755 .npmignore create mode 100755 LICENSE mode change 100644 => 100755 README.md create mode 100755 index.js create mode 100755 package.json create mode 100755 scripts/mocha_runner.js create mode 100755 src/__tests__/index.js create mode 100755 src/index.js diff --git a/.babelrc b/.babelrc new file mode 100755 index 0000000..9620bdf --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015", "stage-2", "react"] +} \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100755 index 0000000..147417b --- /dev/null +++ b/.eslintrc @@ -0,0 +1,51 @@ +{ + "parser": "babel-eslint", + "env": { + "browser": true, + "node": true, + "es6": true + }, + "ecmaFeatures": { + "modules": true + }, + "rules": { + "no-bitwise": 2, + "no-else-return": 2, + "no-eq-null": 2, + "no-extra-parens": 0, + "no-floating-decimal": 2, + "no-inner-declarations": [2, "both"], + "no-lonely-if": 2, + "no-multiple-empty-lines": [2, {"max": 3}], + "no-self-compare": 2, + "no-underscore-dangle": 0, + "no-use-before-define": 0, + "no-unused-expressions": 0, + "no-void": 2, + "brace-style": [2, "1tbs"], + "camelcase": [1, {"properties": "never"}], + "consistent-return": 0, + "comma-style": [2, "last"], + "complexity": [1, 12], + "func-names": 0, + "guard-for-in": 2, + "indent": [2, 4], + "max-len": [0, 120, 4], + "new-cap": [2, {"newIsCap": true, "capIsNew": false}], + "quotes": [2, "single"], + "keyword-spacing": [2, {"before": true, "after": true}], + "space-before-blocks": [2, "always"], + "array-bracket-spacing": [2, "never"], + "space-in-parens": [2, "never"], + "strict": [0], + "valid-jsdoc": 2, + "wrap-iife": [2, "any"], + "yoda": [1, "never"] + }, + "plugins": [ + "react" + ], + "globals": { + + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..fe8ad59 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.swp +*~ +*.iml +.*.haste_cache.* +.DS_Store +.idea +npm-debug.log +node_modules +dist \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100755 index 0000000..59a0c0a --- /dev/null +++ b/.npmignore @@ -0,0 +1,10 @@ +*.swp +*~ +*.iml +.*.haste_cache.* +.DS_Store +.idea +.babelrc +.eslintrc +npm-debug.log +lib diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..6addbc9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Julian Ćwirko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md old mode 100644 new mode 100755 index fed5a47..f51d90b --- a/README.md +++ b/README.md @@ -1 +1,28 @@ -# placeholder-content +# Boilerplate for creating React Npm packages with ES2015 + +The package is based on [npm-base](https://github.com/kadirahq/npm-base) package by [Kadira](https://github.com/kadirahq) which is really great when you want to prepare Npm package. This one is prepared to be used as a starter point for React components which needs to be published on Npm. + +It includes linting with [ESLint](http://eslint.org/) and testing with [Mocha](https://mochajs.org/), [Enzyme](http://airbnb.io/enzyme/) and [JSDOM](https://github.com/tmpvar/jsdom). + +Also there is of course ES6 transpilation. + +## Usage + +1. Clone this repo +2. Inside cloned repo run `npm install` +3. If you want to run tests: `npm test` or `npm run testonly` or `npm run test-watch`. You need to write tests in `__tests__` folder. You need at least Node 4 on your machine to run tests. +4. If you want to run linting: `npm test` or `npm run lint`. Fix bugs: `npm run lint-fix`. You can adjust your `.eslintrc` config file. +5. If you want to run transpilation to ES5 in `dist` folder: `npm run prepublish` (standard npm hook). + +## Blog post about it: + +- [Creating React NPM packages with ES2015](http://julian.io/creating-react-npm-packages-with-es2015/) + +## Also check out + +- [React Alert UI component](https://github.com/juliancwirko/react-s-alert) +- [React project boilerplate with Webpack, HMR, React Router](https://github.com/juliancwirko/react-boilerplate) + +## License + +MIT diff --git a/index.html b/index.html index 3542d19..44938e5 100644 --- a/index.html +++ b/index.html @@ -14,6 +14,7 @@ padding: 30px; box-shadow: 0 3px 10px rgba(0,0,0,.2); background: #fff; + border-radius: 5px; } .gradient { fill: #999; @@ -53,6 +54,7 @@ + diff --git a/index.js b/index.js new file mode 100755 index 0000000..b91eb38 --- /dev/null +++ b/index.js @@ -0,0 +1 @@ +module.exports = require('./dist/index'); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100755 index 0000000..12343f3 --- /dev/null +++ b/package.json @@ -0,0 +1,60 @@ +{ + "name": "react-npm-boilerplate", + "version": "1.0.1", + "description": "Boilerplate for creating React Npm packages with ES2015", + "repository": { + "type": "git", + "url": "https://github.com/juliancwirko/react-npm-boilerplate.git" + }, + "author": "Julian Ćwirko", + "license": "MIT", + "bugs": { + "url": "https://github.com/juliancwirko/react-npm-boilerplate/issues" + }, + "homepage": "https://github.com/juliancwirko/react-npm-boilerplate", + "keywords": [ + "react-component", + "react" + ], + "options": { + "mocha": "--require scripts/mocha_runner src/**/__tests__/**/*.js" + }, + "scripts": { + "watch": "babel --plugins transform-es2015-modules-umd src --watch --ignore __tests__ --out-dir ./dist", + "prepublish": "babel --plugins transform-es2015-modules-umd src --ignore __tests__ --out-dir ./dist", + "lint": "eslint ./src", + "lintfix": "eslint ./src --fix", + "testonly": "mocha $npm_package_options_mocha", + "test": "npm run lint && npm run testonly", + "test-watch": "npm run testonly -- --watch --watch-extensions js" + }, + "devDependencies": { + "babel-cli": "^6.6.4", + "babel-core": "^6.7.4", + "babel-eslint": "^6.0.2", + "babel-plugin-transform-es2015-modules-umd": "^6.6.5", + "babel-polyfill": "^6.7.4", + "babel-preset-es2015": "^6.6.0", + "babel-preset-react": "^6.5.0", + "babel-preset-stage-2": "^6.5.0", + "chai": "^3.5.0", + "enzyme": "^2.2.0", + "eslint": "^2.7.0", + "eslint-plugin-babel": "^3.1.0", + "eslint-plugin-react": "^4.2.3", + "jsdom": "^8.1.0", + "mocha": "^2.4.5", + "nodemon": "^1.9.1", + "react-addons-test-utils": "^15.0.0", + "react": "^15.0.0", + "react-dom": "^15.0.0", + "sinon": "^1.17.3" + }, + "peerDependencies": { + "react": "~0.14.8 || ^15.0.0", + "react-dom": "~0.14.8 || ^15.0.0" + }, + "dependencies": { + "babel-runtime": "^6.6.1" + } +} diff --git a/scripts/mocha_runner.js b/scripts/mocha_runner.js new file mode 100755 index 0000000..7cdd34a --- /dev/null +++ b/scripts/mocha_runner.js @@ -0,0 +1,21 @@ +var jsdom = require('jsdom').jsdom; + +var exposedProperties = ['window', 'navigator', 'document']; + +global.document = jsdom(''); +global.window = document.defaultView; +Object.keys(document.defaultView).forEach((property) => { + if (typeof global[property] === 'undefined') { + exposedProperties.push(property); + global[property] = document.defaultView[property]; + } +}); + +global.navigator = { + userAgent: 'node.js' +}; + +documentRef = document; + +require('babel-core/register'); +require('babel-polyfill'); \ No newline at end of file diff --git a/src/__tests__/index.js b/src/__tests__/index.js new file mode 100755 index 0000000..aee7b55 --- /dev/null +++ b/src/__tests__/index.js @@ -0,0 +1,60 @@ +import React from 'react'; + +import {shallow, mount, render} from 'enzyme'; +import {expect} from 'chai'; +import sinon from 'sinon'; + +import MyComponent from '../index'; + +// Demo tests + +// Shallow Rendering +// https://github.com/airbnb/enzyme/blob/master/docs/api/shallow.md +describe('Shallow Rendering', () => { + + it('to have three `.icon-test`s', () => { + const wrapper = shallow(); + expect(wrapper.find('.icon-test')).to.have.length(3); + }); + + it('simulates click events', () => { + const buttonClick = sinon.spy(); + const wrapper = shallow( + + ); + wrapper.find('button').simulate('click'); + expect(buttonClick.calledOnce).to.equal(true); + }); + +}); + +// Full DOM Rendering +// https://github.com/airbnb/enzyme/blob/master/docs/api/mount.md +describe('Full DOM Rendering', () => { + + it('allows us to set props', () => { + const wrapper = mount(); + expect(wrapper.props().bar).to.equal('baz'); + wrapper.setProps({ bar: 'foo' }); + expect(wrapper.props().bar).to.equal('foo'); + }); + + it('calls componentDidMount', () => { + sinon.spy(MyComponent.prototype, 'componentDidMount'); + const wrapper = mount(); + expect(MyComponent.prototype.componentDidMount.calledOnce).to.be.true; + MyComponent.prototype.componentDidMount.restore(); + }); + +}); + +// Static Rendered Markup +// https://github.com/airbnb/enzyme/blob/master/docs/api/render.md +describe('Static Rendered Markup', () => { + + it('renders three `.icon-test`s', () => { + const wrapper = render(); + expect(wrapper.find('.icon-test').length).to.equal(3); + }); + +}); \ No newline at end of file diff --git a/src/index.js b/src/index.js new file mode 100755 index 0000000..73e23e2 --- /dev/null +++ b/src/index.js @@ -0,0 +1,23 @@ +// Demo component +// this is only example component +// you can find tests in __test__ folder + +import React from 'react'; + +class MyComponent extends React.Component { + componentDidMount() { + // some logic here - we only test if the method is called + } + render() { + return ( +
+ + + + +
+ ) + } +}; + +export default MyComponent; \ No newline at end of file