Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
31 changes: 24 additions & 7 deletions scripts/run-e2e-tests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -181,17 +181,22 @@ async function npmInstall(cwd, prefix) {
*/
async function setupTests(projectPath, prefix) {
const name = path.basename(projectPath);
const log = (...msgs) => console.log(`${info(prefix)}`, ...msgs);
const log = (...msgs) => console.log(info(prefix), ...msgs);
const throwError = (...msgs) => {
process.exitCode = 1;
console.error(error(prefix), ...msgs.map((msg) => error(msg)));
throw new Error(msgs[0]);
};

log(`Beginning E2E test at`, projectPath);
const pkgJsonPath = path.join(projectPath, 'package.json');
if (!(await fileExists(pkgJsonPath))) {
prefix = error(prefix);
console.error(
`${prefix} Could not locate package.json for "${name}". Ensure every e2e test has a package.json defined.`
throwError(
`Could not locate package.json for "${name}".`,
`Ensure every e2e test has a package.json.\n`,
`${prefix} Expected to find one at "${pkgJsonPath}".`
);
console.error(`${prefix} Expected to find one at "${pkgJsonPath}".`);
throw new Error(`Could not locate package.json for "${name}".`);
}

const pkg = JSON.parse(await fs.readFile(pkgJsonPath, 'utf8'));
Expand Down Expand Up @@ -228,10 +233,22 @@ async function setupTests(projectPath, prefix) {
await onExit(cp);
} catch (e) {
process.exitCode = 1;
console.error(error(prefix) + ` Test run failed: ${e.message}`);
throwError(`Test run failed: ${e.message}`);
}

// TODO: validate coverage/lcov.info is not empty
const coveragePath = path.join(projectPath, 'coverage', 'lcov.info');
if (!(await fileExists)) {
throwError(
`Code coverage failed to generate results: Results file does not exist at ${coveragePath}`
);
}

const coverageInfo = await fs.readFile(coveragePath, { encoding: 'utf8' });
if (!coverageInfo) {
throwError(
`Code coverage failed to generate results: Results file is empty`
);
}
};
}

Expand Down
13 changes: 12 additions & 1 deletion src/lib/babel-loader.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
export default function babelLoader(options) {
export function getCoverageBabelLoader() {
return {
test: /\.jsx?$/,
exclude: /node_modules/,
loader: require.resolve('babel-loader'),
query: {
plugins: [require.resolve('babel-plugin-istanbul')],
},
};
}

export function getDefaultBabelLoader(options) {
return {
test: /\.jsx?$/,
exclude: /node_modules/,
Expand Down
36 changes: 20 additions & 16 deletions src/webpack.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import path from 'path';
import delve from 'dlv';
import { tryRequire, dedupe } from './lib/util';
import babelLoader from './lib/babel-loader';
import {
getDefaultBabelLoader,
getCoverageBabelLoader,
} from './lib/babel-loader';
import cssLoader from './lib/css-loader';

/**
Expand Down Expand Up @@ -104,6 +107,21 @@ export function addWebpackConfig(karmaConfig, pkg, options) {
return Object.assign({}, configured || {}, value);
}

let existingBabelLoader = getLoader((rule) =>
`${rule.use},${rule.loader}`.match(/\bbabel-loader\b/)
);
if (existingBabelLoader) {
if (options.coverage) {
loaders.push(getCoverageBabelLoader());
}
} else {
loaders.push(getDefaultBabelLoader(options));
}

if (!getLoader('foo.css')) {
loaders.push(cssLoader(options));
}

for (let prop of Object.keys(karmaConfig.preprocessors)) {
karmaConfig.preprocessors[prop].unshift('webpack');
}
Expand All @@ -115,21 +133,7 @@ export function addWebpackConfig(karmaConfig, pkg, options) {
// devtool: 'module-source-map',
mode: webpackConfig.mode || 'development',
module: {
// @TODO check webpack version and use loaders VS rules as the key here appropriately:
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this TODO is handled by line 180 below so I removed it

//
// TODO: Consider adding coverage as a separate babel-loader so that
// regardless if the user provides their own babel plugins, coverage still
// works
rules: loaders
.concat(
!getLoader((rule) =>
`${rule.use},${rule.loader}`.match(/\bbabel-loader\b/)
)
? babelLoader(options)
: false,
!getLoader('foo.css') && cssLoader(options)
)
.filter(Boolean),
rules: loaders,
},
resolve: webpackProp('resolve', {
modules: webpackProp('resolve.modules', [
Expand Down