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

Using ts-jest for coverage #39

Merged
merged 3 commits into from
Nov 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 50 additions & 23 deletions packages/react-scripts/config/jest/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,66 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/

// This file is a merger between the original transform.js and ts-jest/dist/preprocessor.js (https://github.com/kulshekhar/ts-jest/blob/e1f95e524ed62091736f70abf63530f1f107ec03/src/preprocessor.ts)
// The preprocessor from ts-jest could not be used directly,
// because it did not use babel and
// could not get configuration from the right place (../utils/createJestConfig.js)
// instead it was retrieved from of argv which was incomplete

const babelJest = require('babel-jest');
const tsc = require('typescript');
const glob = require('glob-all');
const nodepath = require('path');
const tsJestUtils = require('ts-jest/dist/utils');
const getPackageRoot = require('jest-util').getPackageRoot;
const root = getPackageRoot();

const babelTransformer = babelJest.createTransformer({
presets: [require.resolve('babel-preset-react-app')]
});

// TODO load tsconfig.json in created app instead of duplicating tsconfig.compilerOptions here
const compilerOptions = {
// Overwrite module
// Jest gives `SyntaxError: Unexpected token import` error when ES6 module are emitted
// module: tsc.ModuleKind.ES6,
module: tsc.ModuleKind.CommonJS,
// Overwrite jsx
// Expected Babel transformer to convert jsx to js
// but Jest gives `SyntaxError: Unexpected token <` error when set to Preserve
// jsx: tsc.JsxEmit.Preserve,
jsx: tsc.JsxEmit.React,
target: tsc.ScriptTarget.ES6,
moduleResolution: tsc.ModuleResolutionKind.NodeJs,
};
function initializeCache(config) {
const collectCoverage = config.collectCoverage;
const coverageDirectory = config.coverageDirectory;
const coverageReporters = config.coverageReporters;
const collectCoverageFrom = config.collectCoverageFrom;
const testResultsProcessor = config.testResultsProcessor;
global.__ts_coverage__cache__ = {};
global.__ts_coverage__cache__.sourceCache = {};
global.__ts_coverage__cache__.coverageConfig = { collectCoverage: collectCoverage, coverageDirectory: coverageDirectory, coverageReporters: coverageReporters };
global.__ts_coverage__cache__.coverageCollectFiles =
collectCoverage &&
testResultsProcessor &&
collectCoverageFrom &&
collectCoverageFrom.length ?
glob.sync(collectCoverageFrom).map(function (x) { return nodepath.resolve(root, x); }) : [];
}

function tsProcess(src, path, config) {
if (path.endsWith('.ts') || path.endsWith('.tsx')) {
if (config.testResultsProcessor && !global.__ts_coverage__cache__) {
// initialize only once
initializeCache(config);
}
var transpiled = tsc.transpileModule(src, {
compilerOptions: tsJestUtils.getTSConfig(config.globals, config.collectCoverage),
fileName: path
});
if (global.__ts_coverage__cache__) {
if (!config.testRegex || !path.match(config.testRegex)) {
global.__ts_coverage__cache__.sourceCache[path] = transpiled.outputText;
}
}
var modified = "require('ts-jest').install();" + transpiled.outputText;
return modified;
}
return src;
}

// transpile the source with TypeScript, if needed, and then with Babel
module.exports = {
process(src, path) {
if (path.endsWith('.ts') || path.endsWith('.tsx')) {
src = tsc.transpile(
src,
compilerOptions,
path,
[]
);
}
process(src, path, config) {
src = tsProcess(src, path, config);
return babelTransformer.process(src, path);
},
};
1 change: 1 addition & 0 deletions packages/react-scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"style-loader": "0.13.1",
"tslint": "^3.15.1",
"tslint-loader": "^2.1.5",
"ts-jest": "^0.1.13",
"typescript": "^2.0.7",
"url-loader": "0.5.7",
"webpack": "1.13.2",
Expand Down
2 changes: 2 additions & 0 deletions packages/react-scripts/template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,8 @@ Run `npm test -- --coverage` (note extra `--` in the middle) to include a covera

Note that tests run much slower with coverage so it is recommended to run it separately from your normal workflow.

The coverage can be found in the `coverage/remapped/` directory in different formats like html and lcov.

### Continuous Integration

By default `npm test` runs the watcher with interactive CLI. However, you can force it to run tests once and finish the process by setting an environment variable called `CI`. Popular CI servers already set it by default but you can do this yourself too:
Expand Down
2 changes: 1 addition & 1 deletion packages/react-scripts/template/src/App.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';

import App from './App';
import { App } from './App';

it('renders without crashing', () => {
const div = document.createElement('div');
Expand Down
18 changes: 13 additions & 5 deletions packages/react-scripts/utils/createJestConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,20 @@

const pathExists = require('path-exists');
const paths = require('../config/paths');
const path = require('path');

module.exports = (resolve, rootDir, isEjecting) => {
// Use this instead of `paths.testsSetup` to avoid putting
// an absolute filename into configuration after ejecting.
const setupTestsFile = pathExists.sync(paths.testsSetup) ? '<rootDir>/src/setupTests.js' : undefined;

const compilerOptions = require(path.resolve('./tsconfig.json')).compilerOptions;
// Jest gives `SyntaxError: Unexpected token import` error when ES6 module are emitted
compilerOptions.module = "commonjs";
// Expected Babel transformer to convert jsx to js
// but Jest gives `SyntaxError: Unexpected token <` error when set to preserve
compilerOptions.jsx = "react";

const config = {
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!src/**/*.d.ts'],
moduleFileExtensions: ['jsx', 'js', 'json', 'ts', 'tsx'],
Expand All @@ -29,14 +37,14 @@ module.exports = (resolve, rootDir, isEjecting) => {
testPathIgnorePatterns: ['<rootDir>/(build|docs|node_modules)/'],
testEnvironment: 'node',
testRegex: "(/__tests__/.*|\.(test|spec))\.(ts|tsx|js|jsx)$",
testResultsProcessor: require.resolve("ts-jest/coverageprocessor"),
scriptPreprocessor: resolve('config/jest/transform.js'),
globals: {
"__TS_CONFIG__": compilerOptions
}
};
if (rootDir) {
config.rootDir = rootDir;
}
if (!isEjecting) {
// This is unnecessary after ejecting because Jest
// will just use .babelrc in the project folder.
config.scriptPreprocessor = resolve('config/jest/transform.js');
}
return config;
};