Prepare Webpack HMR test

This commit is contained in:
Sarah Seo 2016-11-30 06:07:34 +09:00
parent d7202e65a8
commit 7170fdf89a
11 changed files with 260 additions and 35 deletions

16
.babelrc Normal file
View File

@ -0,0 +1,16 @@
{
"presets": [
[
"es2015",
{
"modules": false
}
],
"stage-2",
"react"
],
"plugins": [
"react-hot-loader/babel",
"transform-class-properties"
]
}

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Drafter</title>
<title>Inpad</title>
<style>
#content {
position: absolute;
@ -16,6 +16,7 @@
}
</style>
<link rel="stylesheet" type="text/css" href="../node_modules/octicons/build/octicons.css">
<link rel="stylesheet" type="text/css" href="../node_modules/codemirror/lib/codemirror.css">
</head>
<body>
<div id="content"></div>

36
docs/testing.md Normal file
View File

@ -0,0 +1,36 @@
# Testing
We use custom runner for testing.
## How to
Run webpack dev server
```
npm test:serve
```
Open another terminal and Run test runner
```
npm test:run
```
Then, runner will track changes from `**.spec.js` files in `src` directory and its dependencies and run the needed test.
## `**.spec.js`
Spec file should export test method to `default`.
```
import assert from 'assert'
import StorageManager from './StorageManager'
export default t => {
assert.ok(true)
}
```
## Mocking
This feature is not implemented yet. But, it would be easily solved by using `import-loader`.

View File

@ -1,15 +1,16 @@
{
"name": "Inpad",
"name": "inpad",
"version": "0.1.0",
"description": "A simple note app for developer",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "NODE_ENV=development electron app/index.js",
"pack": "build --dir",
"dist": "build",
"lint": "standard",
"webpack": "NODE_ENV=development webpack-dev-server --config webpack.config.js",
"test:run": "NODE_ENV=test electron ./tools/webpack-test.js",
"test:serve": "NODE_ENV=test webpack-dev-server --config webpack.config.js",
"rebuild": "electron-rebuild"
},
"keywords": [
@ -33,6 +34,7 @@
"electron-devtools-installer": "^2.0.1",
"electron-rebuild": "^1.3.0",
"file-loader": "^0.9.0",
"json-loader": "^0.5.4",
"react-desktop": "^0.2.14",
"react-hot-loader": "^3.0.0-beta.6",
"react-router": "^3.0.0",
@ -45,37 +47,27 @@
},
"dependencies": {
"codemirror": "^5.20.2",
"color": "^0.11.4",
"filenamify": "^1.2.1",
"github-markdown-css": "^2.4.1",
"immutable": "^3.8.1",
"leveldown": "^1.5.0",
"lodash": "^4.16.6",
"moment": "^2.17.0",
"octicons": "^5.0.1",
"pouchdb": "^6.0.7",
"react": "^15.3.2",
"react-dom": "^15.3.2",
"react-redux": "^4.4.5",
"redux": "^3.6.0",
"remark": "^6.2.0",
"remark-emoji": "^1.1.1",
"remark-html": "^5.1.0",
"remark-lint": "^5.2.0",
"sander": "^0.5.1",
"styled-components": "^1.0.10"
},
"standard": {
"parser": "babel-eslint"
},
"babel": {
"presets": [
[
"es2015",
{
"modules": false
}
],
"stage-2",
"react"
],
"plugins": [
"react-hot-loader/babel",
"transform-class-properties"
]
}
}

View File

@ -2,12 +2,14 @@ const sander = require('sander')
const path = require('path')
const PouchDB = require('pouchdb')
const { OrderedMap, Map, Set } = require('immutable')
const util = require('../util')
const util = require('lib/util')
const electron = require('electron')
const { remote } = electron
const storagesPath = path.join(remote.app.getPath('userData'), 'storages')
const storagesPath = process.env.NODE_ENV !== 'test'
? path.join(remote.app.getPath('userData'), 'storages')
: path.join(remote.app.getPath('userData'), 'test-storages')
let dbs
@ -34,7 +36,7 @@ export function init () {
}
// If `storages/notebook` doesn't exist, create it.
if (!dirNames.some((dirName) => dirName === 'notebook')) {
dirNames.unshift(path.join(storagesPath, 'notebook'))
dirNames.unshift('notebook')
}
dbs = dirNames.reduce(function (map, name) {
@ -188,13 +190,14 @@ export function updateNote (name, noteId, payload) {
const db = dbs.get(name)
if (db == null) return Promise.reject(new Error('DB doesn\'t exist.'))
return db.get(noteId)
return db.get('note:' + noteId)
.then((doc) => {
return db
.put({}, doc, payload, {
.put(Object.assign({}, doc, payload, {
_id: doc._id,
_rev: doc._rev
})
_rev: doc._rev,
updatedAt: new Date()
}))
})
}

View File

@ -0,0 +1,23 @@
import assert from 'assert'
import StorageManager from './StorageManager'
// import _ from 'lodash'
export default t => {
let listTest = StorageManager.list()
.then((map) => {
assert.ok(map.size > 0, 'At least, one db should exist')
assert.ok(map.has('notebook'), 'Default DB, notebook, should exist.')
})
let loadAllTest = StorageManager.loadAll()
.then(storageListMap => {
assert.ok(storageListMap.size > 0)
assert.ok(storageListMap.get('notebook').has('notes'))
assert.ok(storageListMap.get('notebook').has('folders'))
})
return Promise.all([
listTest,
loadAllTest
])
}

View File

@ -0,0 +1,58 @@
/**
* # Test entry
*
* Grab `*.spec.js` files
*
* ## TODO
*
* - [ ] Render result as a react
* - [ ] Before/After hook
*
*/
const _ = require('lodash')
function runTest (key, spec, isReloaded) {
if (!_.isFunction(spec.default)) return Promise.reject(new Error('It cannot be excuted. : ' + key))
return Promise.resolve()
.then(() => {
return spec.default()
})
.then(v => {
console.info(`%c${key} ${(isReloaded ? 're-' : '')}tested successfully.`, 'color: green;')
})
.catch(e => {
console.warn('Test failed: ' + key)
throw e
})
}
function loadContext () {
return require.context('../src', true, /\.spec\.js$/)
}
let specContext = loadContext()
let modules = {}
specContext.keys().forEach(function (key) {
let spec = specContext(key)
modules[key] = spec
runTest(key, spec, false)
})
if (module.hot) {
module.hot.accept(specContext.id, function () {
let reloadedContext = loadContext()
let changedModules = reloadedContext.keys()
.map(function (key) {
return [key, reloadedContext(key)]
})
.filter(function (reloadedModule) {
return modules[reloadedModule[0]] !== reloadedModule[1]
})
changedModules.forEach(function (specTuple) {
modules[specTuple[0]] = specTuple[1]
runTest(specTuple[0], specTuple[1], true)
})
})
}

40
tools/webpack-test.html Normal file
View File

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<style>
#content {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
body {
font-family: Helvetica, Arial, sans-serif;
}
</style>
<link rel="stylesheet" type="text/css" href="../node_modules/octicons/build/octicons.css">
<link rel="stylesheet" type="text/css" href="../node_modules/codemirror/lib/codemirror.css">
</head>
<body>
<div id="content"></div>
<script type="text/javascript" src="../node_modules/codemirror/lib/codemirror.js"></script>
<script type="text/javascript" src="../node_modules/codemirror/mode/meta.js"></script>
<script type="text/javascript" src="../node_modules/codemirror/addon/mode/overlay.js"></script>
<script type="text/javascript" src="../node_modules/codemirror/addon/mode/loadmode.js"></script>
<script type="text/javascript" src="../node_modules/codemirror/keymap/sublime.js"></script>
<script type="text/javascript" src="../node_modules/codemirror/addon/runmode/runmode.js"></script>
<script type="text/javascript" src="../node_modules/codemirror/addon/edit/continuelist.js"></script>
<script type="text/javascript" src="../node_modules/react/dist/react.js"></script>
<script type="text/javascript" src="../node_modules/react-dom/dist/react-dom.js"></script>
<script type="text/javascript" src="../node_modules/redux/dist/redux.js"></script>
<script type="text/javascript" src="../node_modules/react-redux/dist/react-redux.js"></script>
<script type="text/javascript" src="../node_modules/immutable/dist/immutable.js"></script>
<script type="text/javascript" src="http://localhost:8081/assets/test.js"></script>
</body>
</html>

21
tools/webpack-test.js Normal file
View File

@ -0,0 +1,21 @@
'use strict'
const electron = require('electron')
const { app, BrowserWindow } = electron
const path = require('path')
let mainWindow = null
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('ready', () => {
mainWindow = new BrowserWindow({
width: 800,
height: 600
})
mainWindow.loadURL('file://' + path.join(__dirname, '/webpack-test.html'))
})

View File

@ -4,26 +4,44 @@ const path = require('path')
const webpack = require('webpack')
const NodeTargetPlugin = require('webpack/lib/node/NodeTargetPlugin')
const config = {
entry: {
const port = process.env.NODE_ENV !== 'test'
? 8080
: 8081
const entry = process.env.NODE_ENV !== 'test'
? {
main: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:8080',
'webpack-dev-server/client?http://localhost:' + port,
'webpack/hot/only-dev-server',
'./src/main/index.js'
]
},
}
: {
test: [
'webpack-dev-server/client?http://localhost:' + port,
'webpack/hot/only-dev-server',
'./tools/webpack-test-entry.js'
]
}
const config = {
entry,
resolve: {
extensions: ['.js', '.jsx'],
alias: {
'components': path.join(__dirname, 'src/components'),
'lib': path.join(__dirname, 'src/lib'),
'main': path.join(__dirname, 'src/main')
}
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new NodeTargetPlugin()
new NodeTargetPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': `"${process.env.NODE_ENV}"`
})
],
externals: [
'electron',
@ -33,12 +51,20 @@ const config = {
'electron-devtools-installer',
'octicons',
'filenamify',
'color',
'moment',
'remark',
'remark-lint',
'remark-html',
'remark-emoji',
'lodash',
{
react: 'var React',
'react-dom': 'var ReactDOM',
'react-redux': 'var ReactRedux',
'redux': 'var Redux',
'immutable': 'var Immutable'
'immutable': 'var Immutable',
'codemirror': 'var CodeMirror'
}
],
module: {
@ -50,7 +76,15 @@ const config = {
loader: 'babel-loader'
}
],
include: path.join(__dirname, 'src')
exclude: /(node_modules|bower_components)/,
},
{
test: /\.json?$/,
use: [
{
loader: 'json-loader'
}
]
}
]
},
@ -59,11 +93,12 @@ const config = {
filename: '[name].js',
sourceMapFilename: '[name].map',
libraryTarget: 'commonjs2',
publicPath: 'http://localhost:8080/assets/'
publicPath: 'http://localhost:' + port + '/assets/'
},
devtool: 'eval',
devServer: {
hot: true
hot: true,
port
}
}