diff --git a/.storybook/config.js b/.storybook/config.js new file mode 100644 index 0000000..a561a88 --- /dev/null +++ b/.storybook/config.js @@ -0,0 +1,9 @@ +import { configure } from '@storybook/react'; + +const req = require.context('../stories', true, /\.js$/) + +function loadStories() { + req.keys().forEach(filename => req(filename)) +} + +configure(loadStories, module); diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html new file mode 100644 index 0000000..3d543d2 --- /dev/null +++ b/.storybook/preview-head.html @@ -0,0 +1 @@ + diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js new file mode 100644 index 0000000..c36d975 --- /dev/null +++ b/.storybook/webpack.config.js @@ -0,0 +1,50 @@ +// you can use this file to add your custom webpack plugins, loaders and anything you like. +// This is just the basic way to add additional webpack configurations. +// For more information refer the docs: https://storybook.js.org/configurations/custom-webpack-config + +// IMPORTANT +// When you add this file, we won't add the default configurations which is similar +// to "React Create App". This only has babel loader to load JavaScript. + +const webpack = require('webpack'); +const precss = require('precss'); +const postcssNested = require('postcss-nested'); +const postcssImport = require('postcss-import'); +const postcssCssnext = require('postcss-cssnext'); + +module.exports = { + plugins: [ + // your custom plugins + ], + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: 'style-loader', + }, + { + loader: 'css-loader', + options: { sourceMap: true, importLoaders: 1 } + }, + { + loader: 'postcss-loader', + options: { + sourceMap: true, + plugins: () => [ + precss(), + postcssNested(), + postcssImport({ addDependencyTo: webpack }), + postcssCssnext({ + browsers: ['last 2 versions', 'ie >= 9'], + compress: true, + }), + ], + }, + }, + ], + } + ] + }, +}; diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..1bfcbf2 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "6" +script: npm run test diff --git a/__fixtures__/index.js b/__fixtures__/index.js new file mode 100644 index 0000000..9ea84d4 --- /dev/null +++ b/__fixtures__/index.js @@ -0,0 +1,9 @@ +import { fromJS } from 'immutable' + +export const exampleData = { + example:{ + result: fromJS({ + testing: 'data' + }) + } +} diff --git a/__mocks__/fileMock.js b/__mocks__/fileMock.js new file mode 100644 index 0000000..86059f3 --- /dev/null +++ b/__mocks__/fileMock.js @@ -0,0 +1 @@ +module.exports = 'test-file-stub'; diff --git a/__tests__/Example.spec.js b/__tests__/Example.spec.js new file mode 100644 index 0000000..6455ecb --- /dev/null +++ b/__tests__/Example.spec.js @@ -0,0 +1,23 @@ +import React from 'react' +import { shallow } from 'enzyme' + +import { Example } from '../src/js/common/components/Example' +import { exampleData } from '../__fixtures__' + +describe('ExampleView', () => { + it('should render a blank div without data', () => { + const el = shallow() + + expect(el.length).toEqual(1) + expect(el.find('.row').length).toEqual(0) + }) + + it('should render with correct data', () => { + const el = shallow( + + ) + + expect(el.length).toEqual(1) + expect(el.find('.row').length).toEqual(1) + }) +}) diff --git a/__tests__/test.js b/__tests__/test.js deleted file mode 100644 index 788441c..0000000 --- a/__tests__/test.js +++ /dev/null @@ -1,5 +0,0 @@ -describe('sum', function() { - it('adds 1 + 2 to equal 3', function() { - expect(1 + 2).toBe(3); - }); -}); \ No newline at end of file diff --git a/package.json b/package.json index 905a23d..daab095 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,16 @@ { "name": "react-redux-boilerplate", - "version": "0.8.20", + "version": "0.8.30", "description": "React Redux Boilerplate is a workflow boilerplate that make life easier for developers by providing a virtual development environment and production ready build process framework out of the box.", "scripts": { "dev": "NODE_ENV=development webpack-dashboard -p 3300 -c red -t dashboard -- node bin/commands.js dev", "build": "NODE_ENV=production node bin/commands.js build", "build:release": "NODE_ENV=release node bin/commands.js build", "clean": "rimraf docroot", - "test": "jest --verbose --no-cache", - "lint": "node bin/commands.js lint" + "test": "jest --no-cache", + "lint": "node bin/commands.js lint", + "storybook": "start-storybook -p 6006", + "build-storybook": "build-storybook -o docroot/doc" }, "repository": { "type": "git", @@ -22,6 +24,7 @@ "node": ">=6.9.0" }, "devDependencies": { + "@storybook/react": "^3.1.8", "assets-webpack-plugin": "^3.5.1", "babel-cli": "^6.24.1", "babel-core": "^6.25.0", @@ -47,6 +50,7 @@ "css-loader": "^0.28.4", "debug": "^2.6.8", "dotenv": "^4.0.0", + "enzyme": "^2.9.1", "eslint": "^3.19.0", "eslint-config-airbnb": "^15.0.2", "eslint-friendly-formatter": "^3.0.0", @@ -56,6 +60,7 @@ "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^0.11.2", "html-webpack-plugin": "^2.29.0", + "identity-obj-proxy": "^3.0.0", "image-webpack-loader": "^3.3.1", "jest-cli": "^20.0.4", "jsonfile": "^3.0.1", @@ -66,6 +71,7 @@ "precss": "^1.4.0", "react-hot-loader": "^3.0.0-beta.6", "react-router": "^4.1.1", + "react-test-renderer": "^15.6.1", "rimraf": "^2.6.1", "shelljs": "^0.7.8", "style-loader": "^0.18.2", @@ -91,10 +97,12 @@ "reselect": "^3.0.1" }, "jest": { - "transform": { - ".*": "/preprocessor.js" + "verbose": true, + "moduleNameMapper": { + "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/__mocks__/fileMock.js", + "\\.(css)$": "identity-obj-proxy" }, - "automock": true, + "automock": false, "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(js|jsx|json)$", "moduleFileExtensions": [ "js", diff --git a/src/assets/fonts/Aspira-Regular.eot b/src/assets/fonts/Aspira-Regular.eot new file mode 100644 index 0000000..8a7d74b Binary files /dev/null and b/src/assets/fonts/Aspira-Regular.eot differ diff --git a/src/assets/fonts/Aspira-Regular.otf b/src/assets/fonts/Aspira-Regular.otf new file mode 100755 index 0000000..cfe0ba0 Binary files /dev/null and b/src/assets/fonts/Aspira-Regular.otf differ diff --git a/src/assets/fonts/fonts.css b/src/assets/fonts/fonts.css new file mode 100644 index 0000000..7008f13 --- /dev/null +++ b/src/assets/fonts/fonts.css @@ -0,0 +1,7 @@ +@font-face { + font-family: "Aspira"; + src: url("Aspira-Regular.eot") format("embedded-opentype"); + src: url("Aspira-Regular.otf") format("opentype"); + font-weight: normal; + font-style: normal; +} diff --git a/src/js/app.jsx b/src/js/app.jsx index 0530225..eae0604 100644 --- a/src/js/app.jsx +++ b/src/js/app.jsx @@ -1,5 +1,7 @@ import React from 'react'; +import '../assets/fonts/fonts.css'; + function App({ children }) { return (
diff --git a/src/js/common/components/Example/Example.jsx b/src/js/common/components/Example/Example.jsx new file mode 100644 index 0000000..9b8f7c0 --- /dev/null +++ b/src/js/common/components/Example/Example.jsx @@ -0,0 +1,24 @@ +import React, { PureComponent } from 'react' + +class Example extends PureComponent { + render () { + const props = this.props; + const result = props.example && props.example.result ? props.example.result : null; + + if (result && result.size && result.size > 0) { + return ( + +
+
+              {JSON.stringify(result.toJS(), undefined, 2)}
+            
+
+ + + ); + } + return
; + } +} + +export default Example diff --git a/src/js/common/components/Example/index.js b/src/js/common/components/Example/index.js new file mode 100644 index 0000000..479da98 --- /dev/null +++ b/src/js/common/components/Example/index.js @@ -0,0 +1 @@ +export { default as Example } from './Example' diff --git a/src/js/views/example/index.jsx b/src/js/views/example/index.jsx index da6eb67..99c2b00 100644 --- a/src/js/views/example/index.jsx +++ b/src/js/views/example/index.jsx @@ -1,8 +1,10 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types' import { connect } from 'react-redux'; + import { actions as exampleActions } from '../../redux/modules/example'; import { exampleSelector } from '../../redux/selectors/exampleSelector'; +import { Example } from '../../common/components/Example' require('../../../style/index.css'); @@ -25,21 +27,7 @@ class ExampleView extends Component { } render() { - const result = this.props.example.result ? this.props.example.result : null; - - if (result && result.size && result.size > 0) { - return ( - -
-
-              {JSON.stringify(result.toJS(), undefined, 2)}
-            
-
- - - ); - } - return
; + return } } diff --git a/src/style/index.css b/src/style/index.css index deeec90..a31b17e 100644 --- a/src/style/index.css +++ b/src/style/index.css @@ -1,5 +1,3 @@ -/* TODO: import is not working - ---------------------- */ @import "configs/color"; /* Example handler @@ -10,3 +8,7 @@ color: brown; font-size: 0.8em; } + +h2 { + font-family: Aspira; +} diff --git a/stories/example.js b/stories/example.js new file mode 100644 index 0000000..8ce78a3 --- /dev/null +++ b/stories/example.js @@ -0,0 +1,9 @@ +import React from 'react'; +import { storiesOf } from '@storybook/react' + +import { Example } from '../src/js/common/components/Example' +import { exampleData } from '../__fixtures__' + +storiesOf('Example View', module) + .add('no data', () => ) + .add('with example data', () => ); diff --git a/webpack.config.common.js b/webpack.config.common.js index 1fd5666..395f01b 100644 --- a/webpack.config.common.js +++ b/webpack.config.common.js @@ -96,7 +96,7 @@ const COMMON_LOADERS = [ ], }, { - test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, + test: /\.[ot]tf(\?v=\d+\.\d+\.\d+)?$/, use: [ { loader: 'url-loader', @@ -111,7 +111,11 @@ const COMMON_LOADERS = [ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, use: [ { - loader: 'file-loader', + loader: 'url-loader', + options: { + limit: 10000, + mimetype: 'application/vnd.ms-fontobject', + } } ], } @@ -153,4 +157,4 @@ export default { tls:'{}', net:'{}' }, -}; \ No newline at end of file +};