Skip to content
This repository has been archived by the owner on Aug 5, 2020. It is now read-only.

Commit

Permalink
Merge pull request #131 from TrueCar/feature/SELA-301
Browse files Browse the repository at this point in the history
SELA-301 Support Mocha without Karma as a test runner.
  • Loading branch information
christinebrass committed May 3, 2016
2 parents bdb60e2 + c75355a commit 9a23602
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 19 deletions.
63 changes: 63 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"parser": "babel-eslint",
"rules": {
"comma-dangle": 0,
"no-cond-assign": [2, "always"],
"no-extra-boolean-cast": 0,

"curly": 2,
"default-case": 2,
"eqeqeq": 2,
"no-case-declarations": 2,
"no-else-return": 2,
"no-fallthrough": 2,
"no-redeclare": 2,
"no-warning-comments": [1, { "terms": ["todo"], "location": "start" }],

"no-undef": 2,
"no-undef-init": 2,
"no-undefined": 2,
"no-unused-vars": 2,

"eol-last": 2,
"indent": [2, 2, {"SwitchCase": 1, "VariableDeclarator": { "var": 2, "let": 2, "const": 3}}],
"jsx-quotes": [2, "prefer-double"],
"linebreak-style": [2, "unix"],
"no-trailing-spaces": 1,
"quotes": [2, "double"],
"semi": [2, "always"],

"no-var": 2,
"prefer-const": 2,

"react/display-name": 0
},
"env": {
"es6": true,
"node": true,
"browser": true
},
"extends": ["eslint:recommended", "plugin:react/recommended"],
"ecmaFeatures": {
"jsx": true,
"experimentalObjectRestSpread": true
},
"plugins": [
"react"
],
"globals": {
"document": true,
"React": true,
"ReactDOM": true,
"window": true,
"describe": true,
"expect": true,
"it": true,
"TestUtils": true,
"sinon": true,
"beforeEach": true,
"afterEach": true,
"before": true,
"after": true
}
}
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"bugs": "https://github.com/TrueCar/gluestick/issues",
"license": "MIT",
"scripts": {
"lint": "eslint src test templates",
"lint": "./node_modules/.bin/eslint src test templates",
"test": "mocha --compilers js:babel-core/register --require babel-polyfill --recursive",
"test-coverage": "./node_modules/.bin/babel-node ./node_modules/babel-istanbul/lib/cli.js cover --include-all-sources --report html --dir coverage/html ./node_modules/.bin/_mocha -- --recursive",
"prepublish": "./docker/generate-dockerfile.js",
Expand Down Expand Up @@ -98,9 +98,11 @@
},
"peerDependencies": {},
"devDependencies": {
"app-module-path": "1.0.6",
"babel-eslint": "6.0.4",
"eslint": "2.9.0",
"eslint-plugin-react": "5.0.1",
"jsdom": "8.5.0",
"temp": "0.8.3"
}
}
14 changes: 11 additions & 3 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,20 @@ const debugOption = {
description: "debug server side rendering with node-inspector"
};

const nodeTestOption = {
command: "-n, --mocha-only",
description: "run tests in Node.js"
};

commander
.command("start")
.description("start everything")
.option("-T, --no_tests", "ignore test hook")
.option(debugOption.command, debugOption.description)
.option(nodeTestOption.command, nodeTestOption.description)
.action(checkGluestickProject)
.action(() => notifyUpdates())
.action((options) => startAll(options.no_tests, options.debug))
.action((options) => startAll(options.no_tests, options.debug, options.mochaOnly))
.action(() => updateLastVersionUsed(currentGluestickVersion));

commander
Expand Down Expand Up @@ -126,6 +132,7 @@ commander
.command("start-test", null, {noHelp: true})
.option(firefoxOption.command, firefoxOption.description)
.option(singleRunOption.command, singleRunOption.description)
.option(nodeTestOption.command, nodeTestOption.description)
.description("start test")
.action(checkGluestickProject)
.action((options) => startTest(options))
Expand All @@ -135,6 +142,7 @@ commander
.command("test")
.option(firefoxOption.command, firefoxOption.description)
.option(singleRunOption.command, singleRunOption.description)
.option(nodeTestOption.command, nodeTestOption.description)
.description("start tests")
.action(checkGluestickProject)
.action(() => updateLastVersionUsed(currentGluestickVersion))
Expand Down Expand Up @@ -193,7 +201,7 @@ function spawnProcess (type, args=[]) {
return childProcess;
}

async function startAll(withoutTests=false, debug=false) {
async function startAll(withoutTests=false, debug=false, mochaOnly=false) {
try {
await autoUpgrade();
}
Expand All @@ -207,7 +215,7 @@ async function startAll(withoutTests=false, debug=false) {

// Start tests unless they asked us not to or we are in production mode
if (!isProduction && !withoutTests) {
spawnProcess("test");
spawnProcess("test", (mochaOnly ? ["--mocha-only"] : []));
}
}

Expand Down
33 changes: 27 additions & 6 deletions src/commands/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,44 @@ const karma = require("karma");
const Server = karma.Server;
const runner = karma.runner;
const karmaConfig = require("../config/karma-config").default;

const config = karmaConfig;
const spawn = require("cross-spawn").spawn;
const path = require("path");
const CWD = process.cwd();

module.exports = function (options) {
// override to run tests in Node without Karma/Webpack
if (options.mochaOnly) {
const helperPath = path.join(__dirname, "..", "lib", "testHelperMocha.js");
const testPath = `${CWD}/test/**/*.test.js`;

// In order to support the Webpack `assets` alias and `src` root, the node path needs to be set up to be
// at the base directory. This allows all module resolves to be relative to the project, rather than to
// Gluestick's CWD.
const mochaEnv = Object.assign({}, process.env, { NODE_PATH: CWD, NODE_ENV: "test" });

// Currently defaulting to "dot" reporter and watch. This can be improved to allow a reporter override
// and single-run.
spawn(
path.join(__dirname, "..", "..", "node_modules", ".bin", "mocha"),
["--require", helperPath, "--reporter", "dot", `${testPath}`, "--watch"],
{ stdio: "inherit", env: mochaEnv }
);
return;
}

// override browser setting to use firefox instead of Chrome if specified
if (options.firefox) {
config.browsers = ["Firefox"];
karmaConfig.browsers = ["Firefox"];
}

if (options.single) {
config.singleRun = options.single;
karmaConfig.singleRun = options.single;
}

const server = new Server(config);
const server = new Server(karmaConfig);

server.start();
server.on("browsers_ready", function () {
runner.run(config, () => {});
runner.run(karmaConfig, () => {});
});
};
2 changes: 1 addition & 1 deletion src/config/karma-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const CWD = process.cwd();
const webpackIsomorphicToolsPlugin = new WebpackIsomorphicToolsPlugin(require("./webpack-isomorphic-tools-config")).development(true);

const preprocessors = {};
const helperPath = path.resolve(__dirname, "../lib/testHelper.js");
const helperPath = path.resolve(__dirname, "../lib/testHelperKarma.js");
preprocessors[helperPath] = ["webpack", "sourcemap"];

export default {
Expand Down
9 changes: 9 additions & 0 deletions src/lib/testHelperKarma.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* global TEST_PATH */
/* global SRC_PATH */
require("./testHelperShared");

const context = require.context(TEST_PATH, true, /\.test\.js$/);
context.keys().forEach(context);

const srcContext = require.context(SRC_PATH, true, /\.js$/);
srcContext.keys().forEach(srcContext);
53 changes: 53 additions & 0 deletions src/lib/testHelperMocha.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* global global */

const CWD = process.cwd();
const IS_WINDOWS = process.platform === "win32";

// Because we have multiple resolves and an alias set up in Webpack, we need to modify require.main.paths at runtime to
// deal with that without the use of a bundler. Unlike require.paths, this is documented and should be safe. However,
// modifying it after anything has been require()d causes cache issues.
//
// Therefore:
// **ACHTUNG** THIS SHOULD ALWAYS BE RUN BEFORE ANY OTHER REQUIRE()s.
//
// Cannot use path.join here since it would take a require()!
require("app-module-path").addPath(CWD + (IS_WINDOWS ? "'" : "/") + "assets");
require("app-module-path").addPath(CWD + (IS_WINDOWS ? "'" : "/") + "src");

require("babel-register");

// Set up jsdom for component rendering through Enzyme.
// This code is directly from Enzyme's docs.
const jsdom = require("jsdom").jsdom;

global.document = jsdom("");
global.window = document.defaultView;
Object.keys(document.defaultView).forEach((property) => {
if (typeof global[property] === "undefined") {
global[property] = document.defaultView[property];
}
});

global.navigator = {
userAgent: "node.js"
};

function noop() {
return null;
}

// Note: require.extensions is deprecated, but is currently the only way to filter out require() of non-JS modules
// without the expense and complication of a pre-compilation step.
//
// From the docs:
//
// "Since the Module system is locked, this feature will probably never go away. However, it may have subtle bugs
// and complexities that are best left untouched."
[".css", ".jpg", ".png", ".scss", ".svg"].forEach((extension) => {
require.extensions[extension] = noop;
});

require("./testHelperShared");

global.expect = require("chai").expect;
global.sinon = require("sinon");
8 changes: 0 additions & 8 deletions src/lib/testHelper.js → src/lib/testHelperShared.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
/*global TEST_PATH*/
/*global SRC_PATH*/
require("babel-polyfill");
const React = require("react");
const ReactDOM = require("react-dom");
const ReactTestUtils = require("react-addons-test-utils");
global.React = React;
global.ReactDOM = ReactDOM;
global.TestUtils = ReactTestUtils;

const context = require.context(TEST_PATH, true, /\.test\.js$/);
context.keys().forEach(context);

const srcContext = require.context(SRC_PATH, true, /\.js$/);
srcContext.keys().forEach(srcContext);

0 comments on commit 9a23602

Please sign in to comment.