diff --git a/package.json b/package.json
index 12a389075..6022a2dcf 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
},
"devDependencies": {
"autoprefixer": "^7.1.1",
- "babel-cli": "^6.23.0",
+ "babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-eslint": "^7.2.3",
"babel-loader": "^7.0.0",
@@ -46,6 +46,7 @@
"babel-preset-env": "^1.4.0",
"babel-preset-react": "^6.24.1",
"chai": "^4.0.2",
+ "chokidar": "^1.7.0",
"core-js": "^2.4.1",
"css-loader": "^0.28.1",
"eslint": "^3.19.0",
@@ -75,6 +76,7 @@
"start": "node source/server.js",
"compile": "NODE_ENV='production' webpack --config source/webpack.config.js",
"surge": "npm run compile && surge --domain scientific-wish.surge.sh -p ./ && rm -rf dist/",
- "test": "mocha-webpack --webpack-config source/webpack.config.js --require source-map-support/register --require __tests__/helpers/browser.js \"__tests__/**/*.test.js\""
+ "test": "mocha-webpack --webpack-config source/webpack.config.js --require source-map-support/register --require test/helpers/browser.js \"test/**/*.test.js\"",
+ "test-fast": "babel-node --presets babel-preset-flow,babel-preset-env --plugins transform-class-properties test/helpers/runner.js"
}
}
diff --git a/source/components/Results.js b/source/components/Results.js
index 1ed9c3f60..0d85a9cb0 100644
--- a/source/components/Results.js
+++ b/source/components/Results.js
@@ -6,8 +6,8 @@ import { withRouter } from 'react-router'
import R from 'ramda'
import './Results.css'
import {capitalise0} from '../utils'
-import {computeRuleValue} from 'Engine/traverse'
-import {encodeRuleName, getObjectives} from 'Engine/rules'
+import {computeRuleValue} from '../engine/traverse'
+import {encodeRuleName, getObjectives} from '../engine/rules'
let fmt = new Intl.NumberFormat('fr-FR').format
let humanFigure = decimalDigits => value => fmt(value.toFixed(decimalDigits))
diff --git a/source/components/Satisfaction.js b/source/components/Satisfaction.js
index 61099a72f..f6c586d2f 100644
--- a/source/components/Satisfaction.js
+++ b/source/components/Satisfaction.js
@@ -1,5 +1,5 @@
import React, {Component} from 'react'
-import HoverDecorator from 'Components/HoverDecorator'
+import HoverDecorator from './HoverDecorator'
import 'whatwg-fetch'
import {connect} from 'react-redux'
import './Satisfaction.css'
diff --git a/source/components/Simulateur.js b/source/components/Simulateur.js
index 286e6bc9e..7ac101ef6 100644
--- a/source/components/Simulateur.js
+++ b/source/components/Simulateur.js
@@ -5,13 +5,13 @@ import {START_CONVERSATION} from '../actions'
import R from 'ramda'
import {Redirect, Link, withRouter} from 'react-router-dom'
import Aide from './Aide'
-import {createMarkdownDiv} from 'Engine/marked'
-import {rules, findRuleByName, decodeRuleName} from 'Engine/rules'
-import 'Components/conversation/conversation.css'
-import 'Components/Simulateur.css'
+import {createMarkdownDiv} from '../engine/marked'
+import {rules, findRuleByName, decodeRuleName} from '../engine/rules'
+import './conversation/conversation.css'
+import './Simulateur.css'
import classNames from 'classnames'
import {capitalise0} from '../utils'
-import Satisfaction from 'Components/Satisfaction'
+import Satisfaction from './Satisfaction'
import Helmet from 'react-helmet'
let situationSelector = formValueSelector('conversation')
diff --git a/source/components/rule/Algorithm.js b/source/components/rule/Algorithm.js
index d14f79f8f..ab75b56b2 100644
--- a/source/components/rule/Algorithm.js
+++ b/source/components/rule/Algorithm.js
@@ -2,8 +2,8 @@ import React from 'react'
import classNames from 'classnames'
import R from 'ramda'
import {AttachDictionary} from '../AttachDictionary'
-import knownMecanisms from 'Engine/known-mecanisms.yaml'
-import marked from 'Engine/marked'
+import knownMecanisms from '../../engine/known-mecanisms.yaml'
+import marked from '../../engine/marked'
@AttachDictionary(knownMecanisms)
export default class Algorithm extends React.Component {
diff --git a/source/components/rule/Examples.js b/source/components/rule/Examples.js
index 02fe288bc..9e73e9667 100644
--- a/source/components/rule/Examples.js
+++ b/source/components/rule/Examples.js
@@ -5,8 +5,8 @@ import {
rules,
decodeRuleName,
disambiguateRuleReference
-} from "Engine/rules.js"
-import { analyseSituation } from "Engine/traverse"
+} from "../../engine/rules.js"
+import { analyseSituation } from "../../engine/traverse"
import "./Examples.css"
export default class Examples extends Component {
diff --git a/source/components/rule/References.js b/source/components/rule/References.js
index b71451418..70ccbd49f 100644
--- a/source/components/rule/References.js
+++ b/source/components/rule/References.js
@@ -1,6 +1,6 @@
import React from 'react'
import R from 'ramda'
-import references from 'Règles/ressources/références/références.yaml'
+import references from '../../../../règles/ressources/références/références.yaml'
import './References.css'
export default ({refs}) => (
@@ -18,7 +18,7 @@ export default ({refs}) => (
{domain}
{refData.image &&
- }
+ }
diff --git a/source/components/rule/Rule.js b/source/components/rule/Rule.js
index 652e8ef5c..6d4e16e30 100644
--- a/source/components/rule/Rule.js
+++ b/source/components/rule/Rule.js
@@ -4,11 +4,11 @@ import {connect} from 'react-redux'
import {formValueSelector} from 'redux-form'
import R from 'ramda'
import './Rule.css'
-import {rules, decodeRuleName} from 'Engine/rules.js'
-import mockSituation from 'Engine/mockSituation.yaml'
-import {analyseSituation} from 'Engine/traverse'
+import {rules, decodeRuleName} from '../../engine/rules.js'
+import mockSituation from '../../engine/mockSituation.yaml'
+import {analyseSituation} from '../../engine/traverse'
import {START_CONVERSATION} from '../../actions'
-import possiblesDestinataires from 'Règles/ressources/destinataires/destinataires.yaml'
+import possiblesDestinataires from '../../../règles/ressources/destinataires/destinataires.yaml'
import {capitalise0} from '../../utils'
import References from './References'
import Algorithm from './Algorithm'
@@ -89,7 +89,7 @@ export default class Rule extends Component {
:
{destinataireData.image &&
- }
+ }
{!destinataireData.image &&
{destinataire}
}
diff --git a/source/containers/Layout.js b/source/containers/Layout.js
index 95e45e096..2ff45f747 100644
--- a/source/containers/Layout.js
+++ b/source/containers/Layout.js
@@ -2,13 +2,13 @@ import React, { Component } from 'react'
import './Layout.css'
import './reset.css'
import {Link, Route, BrowserRouter as Router, Switch} from 'react-router-dom'
-import HomeEmbauche from 'Components/HomeEmbauche'
-import HomeSyso from 'Components/HomeSyso'
-import Rule from 'Components/rule/Rule'
-import Route404 from 'Components/Route404'
-import Contact from 'Components/Contact'
-import Simulateur from 'Components/Simulateur'
-import Results from 'Components/Results'
+import HomeEmbauche from '../components/HomeEmbauche'
+import HomeSyso from '../components/HomeSyso'
+import Rule from '../components/rule/Rule'
+import Route404 from '../components/Route404'
+import Contact from '../components/Contact'
+import Simulateur from '../components/Simulateur'
+import Results from '../components/Results'
export default class Layout extends Component {
diff --git a/source/engine/generateQuestions.js b/source/engine/generateQuestions.js
index d2611dbd5..6a8483319 100644
--- a/source/engine/generateQuestions.js
+++ b/source/engine/generateQuestions.js
@@ -1,9 +1,9 @@
import React from 'react'
-import Explicable from 'Components/conversation/Explicable'
+import Explicable from '../components/conversation/Explicable'
import R from 'ramda'
-import Question from 'Components/conversation/Question'
-import Input from 'Components/conversation/Input'
-import formValueTypes from 'Components/conversation/formValueTypes'
+import Question from '../components/conversation/Question'
+import Input from '../components/conversation/Input'
+import formValueTypes from '../components/conversation/formValueTypes'
import {analyseSituation} from './traverse'
import {formValueSelector} from 'redux-form'
import { STEP_ACTION, START_CONVERSATION} from '../actions'
diff --git a/source/engine/load-rules.js b/source/engine/load-rules.js
index 9360b4ddd..ca1c9fbbb 100644
--- a/source/engine/load-rules.js
+++ b/source/engine/load-rules.js
@@ -1,7 +1,45 @@
import R from 'ramda'
+// This is a mock of webpack's require.context, for testing purposes
+if (typeof require.context === 'undefined') {
+ const fs = require('fs');
+ const path = require('path');
+
+ require.context = (base = '.', scanSubDirectories = false, regularExpression = /\.js$/) => {
+ const yaml = require('js-yaml');
+
+ const files = {};
+
+ function readDirectory(directory) {
+ fs.readdirSync(directory).forEach((file) => {
+ const fullPath = path.resolve(directory, file);
+
+ if (fs.statSync(fullPath).isDirectory()) {
+ if (scanSubDirectories) readDirectory(fullPath);
+
+ return;
+ }
+
+ if (!regularExpression.test(fullPath)) return;
+
+ files[fullPath] = true;
+ });
+ }
+
+ readDirectory(path.resolve(__dirname, base));
+
+ function Module(file) {
+ return yaml.safeLoad(fs.readFileSync(file, 'utf8'));
+ }
+
+ Module.keys = () => Object.keys(files);
+
+ return Module;
+ };
+}
+
// This array can't be generated, as the arguments to require.context must be literals :-|
-let directoryLoaders =
+let directoryLoaders =
[
require.context('../../règles/rémunération-travail/cdd',
true, /([A-Za-z\u00C0-\u017F]|\.|-|_)+.yaml$/),
diff --git a/source/engine/rules.js b/source/engine/rules.js
index 0ea54cfb4..9fb295980 100644
--- a/source/engine/rules.js
+++ b/source/engine/rules.js
@@ -153,12 +153,8 @@ export let collectMissingVariables = (groupMethod='groupByMissingVariable') => a
let isVariant = R.path(['formule', 'une possibilité'])
export let findVariantsAndRecords =
- (allRules, memo, dottedName, childDottedName) => {
- console.log("memo",memo)
- console.log("dottedName",dottedName)
- console.log("childDottedName",childDottedName)
- let {variantGroups, recordGroups} = memo,
- child = findRuleByDottedName(allRules, dottedName),
+ (allRules, {variantGroups, recordGroups}, dottedName, childDottedName) => {
+ let child = findRuleByDottedName(allRules, dottedName),
parentDottedName = parentName(dottedName),
parent = findRuleByDottedName(allRules, parentDottedName)
if (isVariant(parent)) {
diff --git a/source/engine/traverse-common-jsx.js b/source/engine/traverse-common-jsx.js
index 7f51401e8..bc79be27b 100644
--- a/source/engine/traverse-common-jsx.js
+++ b/source/engine/traverse-common-jsx.js
@@ -2,7 +2,7 @@ import React from 'react'
import R from 'ramda'
import classNames from 'classnames'
import {Link} from 'react-router-dom'
-import {encodeRuleName} from 'Engine/rules'
+import {encodeRuleName} from './rules'
let treatValue = data =>
data == null
diff --git a/__tests__/generateQuestions.test.js b/test/generateQuestions.test.js
similarity index 100%
rename from __tests__/generateQuestions.test.js
rename to test/generateQuestions.test.js
diff --git a/__tests__/helpers/browser.js b/test/helpers/browser.js
similarity index 100%
rename from __tests__/helpers/browser.js
rename to test/helpers/browser.js
diff --git a/test/helpers/runner.js b/test/helpers/runner.js
new file mode 100644
index 000000000..ec3534ec9
--- /dev/null
+++ b/test/helpers/runner.js
@@ -0,0 +1,51 @@
+import Mocha from 'mocha';
+import chokidar from 'chokidar';
+
+const fs = require('fs');
+
+const noop = () => {}
+
+const loadYaml = (module, filename) => {
+ const yaml = require('js-yaml');
+ module.exports = yaml.safeLoad(fs.readFileSync(filename, 'utf8'));
+}
+
+const loadNearley = (module, filename) => {
+ var nearley = require('nearley/lib/nearley.js');
+ var compile = require('nearley/lib/compile.js');
+ var generate = require('nearley/lib/generate.js');
+ var grammar = require('nearley/lib/nearley-language-bootstrapped.js');
+
+ var parser = new nearley.Parser(grammar.ParserRules, grammar.ParserStart);
+ parser.feed(fs.readFileSync(filename, 'utf8'));
+ var compilation = compile(parser.results[0], {});
+ var content = generate(compilation, 'Grammar');
+
+ module._compile(content,filename)
+}
+
+require.extensions['.yaml'] = loadYaml
+require.extensions['.ne'] = loadNearley
+require.extensions['.css'] = noop
+
+let fileList = [];
+function runSuite() {
+ Object.keys( require.cache ).forEach( key => delete require.cache[ key ] );
+ const mocha = new Mocha( { reporter: 'dot' } );
+ fileList.forEach( filepath => mocha.addFile( filepath ) );
+ mocha.run();
+}
+
+/**
+ * Chokidar watches all the files for any kind of change and calls the run function
+ * from above. Read more: https://github.com/paulmillr/chokidar
+ * @param {string} a glob of files to watch
+ * @param {object} settings
+ */
+chokidar.watch( 'test/**/*.test.js', { persistent: true } )
+ .on( 'add', path => fileList.push( path ) )
+ .on( 'change', path => runSuite() )
+ .on( 'ready', () => runSuite() );
+
+chokidar.watch( 'source/**/*.js', { persistent: true } )
+ .on( 'change', path => runSuite() )
diff --git a/test/mocha.opts b/test/mocha.opts
new file mode 100644
index 000000000..4092fbfd4
--- /dev/null
+++ b/test/mocha.opts
@@ -0,0 +1,2 @@
+--compilers js:babel-register
+test/**/*.test.js
diff --git a/__tests__/rules.test.js b/test/rules.test.js
similarity index 100%
rename from __tests__/rules.test.js
rename to test/rules.test.js
diff --git a/__tests__/traverse.test.js b/test/traverse.test.js
similarity index 100%
rename from __tests__/traverse.test.js
rename to test/traverse.test.js
diff --git a/__tests__/utils.test.js b/test/utils.test.js
similarity index 100%
rename from __tests__/utils.test.js
rename to test/utils.test.js