diff --git a/package.json b/package.json
index 6de8e63..c21c4c0 100644
--- a/package.json
+++ b/package.json
@@ -33,17 +33,20 @@
"watch-glob": "0.1.3"
},
"devDependencies": {
- "describe-with-dom": "^1.0.0",
"expect": "^1.14.0",
+ "jsdom": "^8.1.0",
+ "jsdom-global": "^1.7.0",
"mocha": "^2.4.5",
"npm-run-all": "^1.5.2",
"react": "^0.14.7",
"react-dom": "^0.14.7",
- "semistandard": "^7.0.5"
+ "semistandard": "^7.0.5",
+ "temp": "^0.8.3"
},
"semistandard": {
"ignore": [
"test/fixtures/**",
+ "test/views/**",
"test-integration/views/**"
]
}
diff --git a/src/transforms/custom-require-visitor.js b/src/transforms/custom-require-visitor.js
index ea34625..5a4c04b 100644
--- a/src/transforms/custom-require-visitor.js
+++ b/src/transforms/custom-require-visitor.js
@@ -1,10 +1,10 @@
var utils = require('jstransform/src/utils');
var globalUtils = require('./utils');
-var requireRegister = require.resolve('../proxies').replace(/\\/g, '/');
+var proxiesPath = require.resolve('../proxies').replace(/\\/g, '/');
function requireVisitor (traverse, node, path, state) {
if (!state.g.alreadyAddedElectronHotRequire) {
- utils.append("var __electronHot__ = require('" + requireRegister + "');\n", state);
+ utils.append("var __electronHot__ = require('" + proxiesPath + "');\n", state);
state.g.alreadyAddedElectronHotRequire = true;
}
diff --git a/test-integration/hot-reload.spec.js b/test-integration/hot-reload.spec.js
new file mode 100644
index 0000000..35d7818
--- /dev/null
+++ b/test-integration/hot-reload.spec.js
@@ -0,0 +1,96 @@
+/* global describe,it,before,after */
+'use strict';
+
+const expect = require('expect');
+var jsdom = require('jsdom-global');
+const fs = require('fs');
+const os = require('os');
+const path = require('path');
+const temp = require('temp').track();
+
+let rootDir;
+let cleanup;
+
+describe('loadJsx', function () {
+ this.timeout(10000);
+
+ before(() => {
+ cleanup = jsdom();
+ const electronHot = require('../src/index');
+ electronHot.install();
+
+ rootDir = temp.mkdirSync('electron-hot');
+ createTempJsx('./views/index.jsx');
+ createTempJsx('./views/App.jsx');
+
+ // Strange bug on OSX
+ const cwd = os.platform() === 'darwin' ? '/private' + rootDir : rootDir;
+ electronHot.watchJsx(['**/*.jsx'], {cwd: cwd, delay: 0});
+ });
+
+ it('should hot reload JSX files', (done) => {
+ const indexJsx = path.join(rootDir, 'index.jsx');
+ const appJsx = path.join(rootDir, 'App.jsx');
+
+ require(indexJsx);
+
+ // our html contains Hello
+ expect(getHtmlBody()).toContain('Hello');
+
+ doLater(() => changeFile(appJsx, content => content.replace('Hello', 'Hi')))
+ .then(() => waitFor(() => getHtmlBody().match('Hi')))
+ .then(done);
+ });
+
+ after(() => {
+ cleanup();
+ delete require.extensions['.jsx'];
+ temp.cleanupSync();
+ });
+});
+
+function waitFor (condition) {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ const interval = setInterval(() => {
+ if (condition()) {
+ clearInterval(interval);
+ resolve();
+ }
+ }, 100);
+ }, 0);
+ });
+}
+
+function doLater (thing) {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ thing();
+ resolve();
+ }, 500);
+ });
+}
+
+function changeFile (filePath, transform) {
+ let content = fs.readFileSync(filePath).toString();
+ content = transform(content);
+ fs.writeFileSync(filePath, content);
+}
+
+function getHtmlBody () {
+ return document.defaultView.document.documentElement.outerHTML;
+}
+
+function createTempJsx (source) {
+ let content = fs.readFileSync(require.resolve(source)).toString();
+
+ const reactPath = require.resolve('react').replace(/\\/g, '/');
+ content = content.replace("require('react')", `require('${reactPath}')`);
+
+ const reactDOMPath = require.resolve('react-dom').replace(/\\/g, '/');
+ content = content.replace("require('react-dom')", `require('${reactDOMPath}')`);
+
+ const sourceFileName = path.basename(source);
+ fs.writeFileSync(path.join(rootDir, sourceFileName), content);
+}
+
diff --git a/test-integration/mocha.opts b/test-integration/mocha.opts
index 8dfda54..178dfe3 100644
--- a/test-integration/mocha.opts
+++ b/test-integration/mocha.opts
@@ -1,5 +1,4 @@
-u bdd
---recursive ./test-integration/**/*spec.jsx
+--recursive ./test-integration/**/*spec.js
--full-trace
--reporter spec
---require ./compiler
\ No newline at end of file
diff --git a/test-integration/views/index.jsx b/test-integration/views/index.jsx
new file mode 100644
index 0000000..04c360e
--- /dev/null
+++ b/test-integration/views/index.jsx
@@ -0,0 +1,9 @@
+const React = require('react');
+const ReactDOM = require('react-dom');
+
+console.debug = () => {};
+
+const App = require('./App.jsx');
+const element = document.createElement('div');
+document.body.appendChild(element);
+ReactDOM.render(, element);
diff --git a/test-integration/load.spec.jsx b/test/spec/error.spec.js
similarity index 59%
rename from test-integration/load.spec.jsx
rename to test/spec/error.spec.js
index 22f9bbe..0e9f199 100644
--- a/test-integration/load.spec.jsx
+++ b/test/spec/error.spec.js
@@ -1,34 +1,29 @@
-/* global it */
+/* global it,describe,before,after */
'use strict';
const expect = require('expect');
-const describeWithDom = require('describe-with-dom');
-const React = require('react');
-const ReactDOM = require('react-dom');
-
-describeWithDom('loadJsx', () => {
- it('should load a JSX file', () => {
- const App = require('./views/App.jsx');
- const element = document.createElement('div');
- document.body.appendChild(element);
- ReactDOM.render(, element);
-
- var window = document.defaultView;
- expect(window.document.documentElement.outerHTML).toContain('Hello');
+describe('loadJsx', () => {
+ before(() => {
+ const electronHot = require('../../src/index');
+ electronHot.install();
});
it('should throw when a component contains an error', () => {
- const exceptionMessage = getExceptionMessage(() => require('./views/ErrorComponent.jsx'));
+ const exceptionMessage = getExceptionMessage(() => require('./../views/ErrorComponent.jsx'));
expect(exceptionMessage)
.toMatch(/^Error compiling [\w\/\-\\:]+?ErrorComponent\.jsx: Parse Error: Line 10: Unexpected token }/);
});
it('should throw a simple error when a component contains a component which contains an error', () => {
- const exceptionMessage = getExceptionMessage(() => require('./views/AppUsingErrorComponent.jsx'));
+ const exceptionMessage = getExceptionMessage(() => require('./../views/AppUsingErrorComponent.jsx'));
expect(exceptionMessage)
.toMatch(/^Error compiling [\w\/\-\\:]+?ErrorComponent\.jsx: Parse Error: Line 10: Unexpected token }/);
});
+
+ after(() => {
+ delete require.extensions['.jsx'];
+ });
});
function getExceptionMessage (executor) {
diff --git a/test-integration/views/AppUsingErrorComponent.jsx b/test/views/AppUsingErrorComponent.jsx
similarity index 100%
rename from test-integration/views/AppUsingErrorComponent.jsx
rename to test/views/AppUsingErrorComponent.jsx
diff --git a/test-integration/views/ErrorComponent.jsx b/test/views/ErrorComponent.jsx
similarity index 100%
rename from test-integration/views/ErrorComponent.jsx
rename to test/views/ErrorComponent.jsx