diff --git a/packages/electrode-archetype-react-app-dev/config/archetype.js b/packages/electrode-archetype-react-app-dev/config/archetype.js index a4225e340..b63715c0b 100644 --- a/packages/electrode-archetype-react-app-dev/config/archetype.js +++ b/packages/electrode-archetype-react-app-dev/config/archetype.js @@ -41,7 +41,8 @@ module.exports = { istanbul: `${configDir}/istanbul`, karma: `${configDir}/karma`, mocha: `${configDir}/mocha`, - webpack: `${configDir}/webpack` + webpack: `${configDir}/webpack`, + jest: `${configDir}/jest` }, archetypeOptions.configPaths ) diff --git a/packages/electrode-archetype-react-app-dev/config/babel/babelrc-client b/packages/electrode-archetype-react-app-dev/config/babel/babelrc-client index 7113cb15a..08f07309e 100644 --- a/packages/electrode-archetype-react-app-dev/config/babel/babelrc-client +++ b/packages/electrode-archetype-react-app-dev/config/babel/babelrc-client @@ -52,6 +52,9 @@ "transform-runtime" ], "env": { + "test": { + "plugins": ["dynamic-import-node"] + }, "production": { "plugins": [ "babel-plugin-transform-react-constant-elements", diff --git a/packages/electrode-archetype-react-app-dev/config/jest/__mocks__/file-mock.js b/packages/electrode-archetype-react-app-dev/config/jest/__mocks__/file-mock.js new file mode 100644 index 000000000..ea1367c1e --- /dev/null +++ b/packages/electrode-archetype-react-app-dev/config/jest/__mocks__/file-mock.js @@ -0,0 +1,3 @@ +// __mocks__/fileMock.js + +module.exports = "test-file-stub"; diff --git a/packages/electrode-archetype-react-app-dev/config/jest/__mocks__/framework-mock.js b/packages/electrode-archetype-react-app-dev/config/jest/__mocks__/framework-mock.js new file mode 100644 index 000000000..1b86882f3 --- /dev/null +++ b/packages/electrode-archetype-react-app-dev/config/jest/__mocks__/framework-mock.js @@ -0,0 +1,5 @@ +const Enzyme = require("enzyme"); +const EnzymeAdapter = require("enzyme-adapter-react-16"); + +// Setup enzyme's react adapter +Enzyme.configure({ adapter: new EnzymeAdapter() }); diff --git a/packages/electrode-archetype-react-app-dev/config/jest/jest.config.js b/packages/electrode-archetype-react-app-dev/config/jest/jest.config.js new file mode 100644 index 000000000..a36c726cb --- /dev/null +++ b/packages/electrode-archetype-react-app-dev/config/jest/jest.config.js @@ -0,0 +1,31 @@ +const Path = require("path"); +const optionalRequire = require("optional-require")(require); + +const rootDir = process.cwd(); +const devPkgPath = Path.join(__dirname, "../.."); + +const jestPath = Path.join(devPkgPath, "config", "jest"); +const fileMock = Path.join(jestPath, "__mocks__", "file-mock.js"); +const frameworkMock = Path.join(jestPath, "__mocks__", "framework-mock.js"); + +const archetypeOptions = optionalRequire(Path.resolve("archetype", "config"), { + default: {} +}); + +const jestDefaultConfig = { + rootDir, + moduleFileExtensions: ["js", "jsx"], + moduleDirectories: ["node_modules", "src"], + moduleNameMapper: { + "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": fileMock, + "\\.(css|less)$": "identity-obj-proxy" + }, + setupTestFrameworkScriptFile: frameworkMock, + modulePathIgnorePatterns: ["/test"] +}; + +module.exports = Object.assign( + {}, + jestDefaultConfig, + archetypeOptions.jest +); diff --git a/packages/electrode-archetype-react-app-dev/config/karma/entry.js b/packages/electrode-archetype-react-app-dev/config/karma/entry.js index 57c85b141..7120596d2 100644 --- a/packages/electrode-archetype-react-app-dev/config/karma/entry.js +++ b/packages/electrode-archetype-react-app-dev/config/karma/entry.js @@ -54,7 +54,7 @@ window.mocha.setup({ // Use webpack to include all app code _except_ the entry point so we can get // code coverage in the bundle, whether tested or not. // NOTE: No need to specify src even in src mode since webpack should handle that already -var srcReq = require.context("client", true, /^((?!app).)*\.jsx?$/); +var srcReq = require.context("client", true, /^((?!app).)(!(spec|test))*\.(jsx|js)?$/); srcReq.keys().map(srcReq); // Use webpack to infer and `require` tests automatically only for test/client diff --git a/packages/electrode-archetype-react-app-dev/package.json b/packages/electrode-archetype-react-app-dev/package.json index 3efd996b4..8b136653b 100644 --- a/packages/electrode-archetype-react-app-dev/package.json +++ b/packages/electrode-archetype-react-app-dev/package.json @@ -25,6 +25,7 @@ "babel-core": "^6.4.0", "babel-eslint": "^8.1.2", "babel-loader": "^7.0.0", + "babel-jest": "^22.4.3", "babel-plugin-i18n-id-hashing": "^2.1.0", "babel-plugin-lodash": "^3.1.3", "babel-plugin-minify-dead-code-elimination": "^0.1.7", @@ -35,6 +36,7 @@ "babel-plugin-transform-react-inline-elements": "^6.6.5", "babel-plugin-transform-react-remove-prop-types": "^0.4.8", "babel-plugin-transform-runtime": "^6.8.0", + "babel-plugin-dynamic-import-node": "^1.2.0", "babel-polyfill": "^6.5.0", "babel-preset-env": "^1.6.1", "babel-preset-react": "^6.3.13", @@ -60,9 +62,11 @@ "file-loader": "^0.11.1", "fs-extra": "^0.26.5", "glob": "^7.0.6", + "identity-obj-proxy": "^3.0.0", "isomorphic-loader": "^2.0.0", "isparta": "^4.0.0", "istanbul": "^0.4.5", + "jest": "^22.4.3", "json-loader": "^0.5.7", "jsonfile": "^2.2.2", "karma": "^1.7.1", diff --git a/packages/electrode-archetype-react-app/arch-clap.js b/packages/electrode-archetype-react-app/arch-clap.js index c08cfb624..35977bbb6 100644 --- a/packages/electrode-archetype-react-app/arch-clap.js +++ b/packages/electrode-archetype-react-app/arch-clap.js @@ -6,6 +6,7 @@ const Fs = require("fs"); const archetype = require("./config/archetype"); const assert = require("assert"); const requireAt = require("require-at"); +const glob = require("glob"); assert(!archetype.noDev, "dev archetype is missing - development & build tasks not possible"); @@ -670,7 +671,8 @@ Individual .babelrc files were generated for you in src/client and src/server "test-cov": [ ".build.test.client.babelrc", ".build.test.server.babelrc", - "test-frontend-cov", + "karma-test-frontend-cov", + "jest-test-frontend-cov", "test-server-cov" ], "test-dev": ["test-frontend-dev", "test-server-dev"], @@ -688,11 +690,28 @@ Individual .babelrc files were generated for you in src/client and src/server `--colors` ), - "test-frontend-cov": mkCmd( - `karma start`, - quote(karmaConfig("karma.conf.coverage.js")), - `--colors` - ), + "karma-test-frontend-cov": () => { + if (shell.test("-d", "test")) { + logger.info("\nRunning Karma unit tests:\n"); + return mkCmd( + `~$karma start`, + quote(karmaConfig("karma.conf.coverage.js")), + `--colors` + ) + } + return undefined; + }, + "jest-test-frontend-cov": () => { + const srcJestFiles = glob.sync(`${Path.resolve(AppMode.src.dir)}/**/\*.{test,spec}.{js,jsx}`); + + if (shell.test("-d", "_test_") || srcJestFiles.length > 0) { + logger.info("\nRunning jest unit tests:\n"); + return mkCmd( + `~$jest`, + `--config ${archetype.config.jest}/jest.config.js` + ) + } + }, "test-frontend-dev": () => exec(`pgrep -fl "webpack-dev-server.*${archetype.webpack.testPort}"`)