Skip to content

Commit

Permalink
Create a working React/Webpack project, with Jasmine unit tests that …
Browse files Browse the repository at this point in the history
…demonstrate the functionality of the plugin.
  • Loading branch information
xml committed May 3, 2016
1 parent 4be829d commit de4c1e5
Show file tree
Hide file tree
Showing 13 changed files with 332 additions and 0 deletions.
4 changes: 4 additions & 0 deletions demo/.babelrc
@@ -0,0 +1,4 @@
{
plugins: ['transform-runtime', 'transform-decorators-legacy'],
presets: ['es2015', 'stage-0', 'react']
}
40 changes: 40 additions & 0 deletions demo/.gitignore
@@ -0,0 +1,40 @@
# temp files
.DS_Store
.tmp
.sass-cache

# package-management
node_modules/
.bin/
bower_components/
npm-debug.log

# build folder
dist/

# IDE
*.sublime-project
*.sublime-workspace
.idea/


# Thumbnails
# ._*


### OSX ###
.AppleDouble
.LSOverride
Icon

### Windows ###
# Windows image file caches
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

24 changes: 24 additions & 0 deletions demo/README.md
@@ -0,0 +1,24 @@
# Just a Demo

### Purpose
This demo provides a working example of the Case Sensitive Paths - Webpack Plugin in action. The demo source is just a basic React app compiled with Webpack. The unit-tests show that attempting to `import` modules that are spelled correctly - but with incorrect cases in the filename or path - will result in a Webpack build error.

### Use
To run the demo project:

* clone the full plugin repo
* `cd /demo`
* `npm install`
* `npm start`

To run the demo tests:
* (everything above)
* `npm test`

You should see 3 passed tests and 2 errors: `Module not found: Error: CaseSensitivePathsPlugin:`. In those examples, we've deliberately misspelled the cases of a module name or path, and the plugin has caused Webpack to throw an error during build.


Note the following:

* If you want to test the plugin like this in your own project, and you have a separate webpack config for testing (this one is in karma.conf.js), you'll need to also include the plugin there.
* This demo is based on patterns borrowed from a host of React/Webpack seed projects, but it's impossible to say which parts from where. Many thanks to the robust React community for providing such excellent tooling!
38 changes: 38 additions & 0 deletions demo/karma.conf.js
@@ -0,0 +1,38 @@
// karma.conf.js
const webpack = require('webpack');
const wpc = require('./webpack.config');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');


module.exports = function(config) {
config.set({
browsers: ['PhantomJS', 'Chrome'],
singleRun: true,
frameworks: ['jasmine'],
files: [
'./node_modules/phantomjs-polyfill/bind-polyfill.js',
'tests.webpack.js'
],
preprocessors: {
'tests.webpack.js': ['webpack', 'sourcemap']
},
webpack: {
devtool: 'inline-sourcemap',
resolve: wpc.resolve, // get from main webpack config
module: {
loaders: wpc.module.loaders, // get from main webpack config
},
watch: true,
plugins: [
new webpack.DefinePlugin({
__ENV__: JSON.stringify('dev') // always test in 'dev' environment
}),
// Mac doesn't care about case, but linux servers do, so enforce...
new CaseSensitivePathsPlugin()
],
},
webpackServer: {
noInfo: true
}
});
};
56 changes: 56 additions & 0 deletions demo/package.json
@@ -0,0 +1,56 @@
{
"name": "casesensitivepathswebpackpluginDemo",
"version": "0.0.1",
"engines": {
"node": "^4 || ^5"
},
"engine-strict": true,
"description": "just a simple demo for showing config and how to E2E test",
"main": "app.js",
"src": "src",
"test": "test",
"dist": "dist",
"mainInput": "main",
"mainOutput": "main",
"scripts": {
"start": "NODE_ENV=dev node ./servers/server.js",
"test": "./node_modules/.bin/karma start --single-run --browsers PhantomJS --reporters dots",
"build": "./node_modules/.bin/webpack --config ./webpack.config.js --progress --colors -p"
},
"author": "Urthen & XML",
"license": "MIT",
"dependencies": {
"babel-polyfill": "^6.7.4",
"babel-runtime": "^6.6.1",
"react": "^15.0.0",
"react-dom": "^15.0.0"
},
"devDependencies": {
"babel-core": "^6.0.0",
"babel-eslint": "^6.0.0",
"babel-loader": "^6.0.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-runtime": "^6.6.0",
"babel-preset-es2015": "^6.0.0",
"babel-preset-react": "^6.0.0",
"babel-preset-stage-0": "^6.0.0",
"case-sensitive-paths-webpack-plugin": "^1.0.1",
"html-webpack-plugin": "^1.6.1",
"jasmine": "^2.3.2",
"jasmine-core": "^2.3.4",
"karma": "^0.13.9",
"karma-chrome-launcher": "^0.2.0",
"karma-cli": "^0.1.0",
"karma-coverage": "^0.5.2",
"karma-jasmine": "^0.3.6",
"karma-phantomjs-launcher": "^0.2.1",
"karma-sourcemap-loader": "^0.3.5",
"karma-webpack": "^1.7.0",
"phantomjs": "^1.9.19",
"phantomjs-polyfill": "0.0.2",
"react-addons-test-utils": "^0.14.8",
"react-hot-loader": "^1.3.0",
"webpack": "~1.12.0",
"webpack-dev-server": "~1.14.1"
}
}
20 changes: 20 additions & 0 deletions demo/servers/server.js
@@ -0,0 +1,20 @@
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const config = require('../webpack.config');

const host = '0.0.0.0'; // allows connection from external devices
const portNum = 3000;

new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
historyApiFallback: true,
contentBase: 'src/',
stats: { colors: true }
}).listen(portNum, host, function (err, result) {
if (err) {
return console.log(err);
}

console.log('Listening at http://' + host + ':' + portNum + '/');
});
21 changes: 21 additions & 0 deletions demo/src/AppRoot.component.js
@@ -0,0 +1,21 @@
import React, { Component } from 'react';

export default class AppRoot extends Component {
// we can't use `connect` in this component, so must do naiively:

constructor(props) {
super(props);
this.state = {

};
}

render() {
return (
<div>
<h1>This is just an empty demo</h1>
<p>(Run the tests.)</p>
</div>
);
}
}
12 changes: 12 additions & 0 deletions demo/src/index.html
@@ -0,0 +1,12 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="react-app-hook">
</div>
<!-- main.js is produced by Webpack -->
<script type="text/javascript" src="/main.js"></script>
</body>
</html>
11 changes: 11 additions & 0 deletions demo/src/init.js
@@ -0,0 +1,11 @@
import AppRoot from './AppRoot.component.js';
import React from 'react';
import ReactDOM from 'react-dom';

const app = {
initialize() {
ReactDOM.render(<AppRoot/>, document.getElementById('react-app-hook'));
}
};

app.initialize();
3 changes: 3 additions & 0 deletions demo/src/utils/api.js
@@ -0,0 +1,3 @@
export default function() {
console.log('Hello, universe.');
};
15 changes: 15 additions & 0 deletions demo/test/case-sensitive-paths-test.js
@@ -0,0 +1,15 @@
describe("Case-Sensitive Paths Plugin", () => {
it('shouldn\'t interfere with correctly-spelled imports', () => {
const getUser1 = require('../src/utils/api');
expect(getUser1).toBeDefined();
});

it('should cause mistakes in filename case to fail import', () => {
expect(() => {const getUser2 = require('../src/utils/API');}).toThrow();
});

it('should cause mistakes in path case to fail import', () => {
expect(() => {const getUser3 = require('../src/Utils/api');}).toThrow();
});

});
3 changes: 3 additions & 0 deletions demo/tests.webpack.js
@@ -0,0 +1,3 @@
// tests.webpack.js
var context = require.context('./test', true, /-test\.(js|jsx)$/);
context.keys().forEach(context);
85 changes: 85 additions & 0 deletions demo/webpack.config.js
@@ -0,0 +1,85 @@
var webpack = require('webpack');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');

// We use the NODE_ENV in our automation commands to differentiate environments
var production =
process.env.NODE_ENV === 'production' ||
process.env.NODE_ENV === 'preprod';

// Setup our plugins.
var plugins = [
// attaches the webpack-generated JS to our main HTML file
new HtmlWebpackPlugin({template: './src/index.html'}),
// create global access to the NODE_ENV within our Webpacked code:
new webpack.DefinePlugin({
__ENV__: JSON.stringify(process.env.NODE_ENV)
}),
// http://gaearon.github.io/react-hot-loader/getstarted/
new webpack.HotModuleReplacementPlugin(),
// Mac doesn't care about case, but linux servers do, so enforce...
new CaseSensitivePathsPlugin()
];

// In production we do a bit more...
if (production) {
plugins.concat(
[
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]);
}

const devEntry = [
'webpack-dev-server/client?http://0.0.0.0:3000', // tells client where to get hot reloads
'webpack/hot/only-dev-server', // "only" prevents reload on syntax errors
'babel-polyfill', // for full ES6 compatibility on older devices
'./src/init.js'
];
const prodEntry = [
'babel-polyfill', // for full ES6 compatibility on older devices
'./src/init.js'
];

const theEntry = (production) ? prodEntry : devEntry;

module.exports = {

// Bundle to our dist folder as a main.js file.
output: {
path: path.join(__dirname, 'dist'),
filename: 'main.js',
publicPath: '/'
},

devtool: 'sourcemap',

// Our master entry point.
entry: theEntry,

// Extra helpers to make require or include easier.
resolve: {
extensions: ['', '.js', '.jsx', '.json']
},

module: {
loaders: [{
test: /\.(js|jsx)$/,
// in dev only, hotload
loader: production ? 'babel' : 'react-hot!babel',
// other babel options are specified in .babelrc
exclude: /node_modules/
}, {
test: /\.json$/,
loader: 'json'
}]
},

plugins: plugins
};

0 comments on commit de4c1e5

Please sign in to comment.