Skip to content
Open
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
28 changes: 28 additions & 0 deletions packages/ember-cli-code-coverage/addon-test-support/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { helper } from '@ember/component/helper';

let __require;

if (typeof __webpack_require__ !== 'undefined') {
Expand Down Expand Up @@ -111,3 +113,29 @@ function writeCoverageInfo(data) {
document.body.appendChild(element);
}
}

export const emberCliCodeCoverageIncrement = helper(
function emberCliCodeCoverageIncrement(params, hash) {
let { path, statement, branch, condition, action } = hash;

if (action) {
return function (...arg) {
if (statement) {
window.__coverage__[path].s[statement]++;
}

return params[0].call(this, ...arg);
};
}

if (statement) {
window.__coverage__[path].s[statement]++;
}

if (branch && condition != null) {
window.__coverage__[path].b[branch][condition]++;
}

return params[0];
}
);
59 changes: 57 additions & 2 deletions packages/ember-cli-code-coverage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ module.exports = {
configBase = pkgJSON['ember-addon'].configPath;
}

let config = {};

if (fs.existsSync(path.join(cwd, configBase, 'coverage.js'))) {
let config = require(path.join(cwd, configBase, 'coverage.js'));
config = require(path.join(cwd, configBase, 'coverage.js'));

if (config.excludes) {
exclude = config.excludes;
Expand Down Expand Up @@ -90,7 +92,24 @@ module.exports = {
// String lookup is needed to workaround https://github.com/embroider-build/embroider/issues/1525
path.resolve(__dirname, 'lib/gjs-gts-istanbul-ignore-template-plugin'),
[IstanbulPlugin, { cwd, include: '**/*', exclude, extension }],
];
].concat(
config.enableTemplateCoverage
? [
[
// eslint-disable-next-line node/no-missing-require
require.resolve('babel-plugin-ember-template-compilation'),
{
transforms: [this.buildTemplatePlugin({ cwd, exclude })],
enableLegacyModules: [
'ember-cli-htmlbars',
'ember-cli-htmlbars-inline-precompile',
'htmlbars-inline-precompile',
],
},
],
]
: []
);
},

includedCommands() {
Expand All @@ -99,6 +118,23 @@ module.exports = {
};
},

_isCoverageEnabled() {
let config = this.project.config(process.env.EMBER_ENV)[this.name] || {};
return process.env[config.coverageEnvVar || 'COVERAGE'] === 'true';
},

treeForAddon() {
if (this._isCoverageEnabled()) {
return this._super.treeForAddon.apply(this, arguments);
}
},

treeForApp() {
if (this._isCoverageEnabled()) {
return this._super.treeForApp.apply(this, arguments);
}
},

buildNamespaceMappings() {
let rootNamespaceMappings = new Map();
function recurse(item) {
Expand Down Expand Up @@ -165,4 +201,23 @@ module.exports = {
namespaceMappings: this.buildNamespaceMappings(),
};
},

buildTemplatePlugin(params = {}) {
const buildTemplateInstrumenter = require('./lib/template-instrumenter');
let plugin = buildTemplateInstrumenter(params);

plugin._parallelBabel = {
requireFile: __filename,
buildUsing: 'buildTemplatePlugin',
params,
};
plugin.baseDir = function () {
return __dirname;
};
plugin.cacheKey = function () {
return 'template-instrumenter';
};

return plugin;
},
};
70 changes: 70 additions & 0 deletions packages/ember-cli-code-coverage/lib/template-coverage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const LINE_ENDINGS = /(?:\r\n?|\n)/;

function getLocation({ loc }) {
return {
start: {
line: loc && loc.start.line,
column: loc && loc.start.column,
},
end: {
line: loc && loc.end.line,
column: loc && loc.end.column,
},
};
}

class TemplateCoverage {
constructor(path, contents) {
this.data = {
path,
s: {},
b: {},
f: {},
fnMap: {},
statementMap: {},
branchMap: {},
code: contents ? contents.split(LINE_ENDINGS) : [],
};

this._currentStatement = 0;
this._currentBranch = 0;
}

newStatement(node) {
this._currentStatement++;
this.data.s[this._currentStatement] = 0;
this.data.statementMap[this._currentStatement] = getLocation(node);

return this._currentStatement;
}

newBlock(node) {
this._currentBranch++;
this.data.b[this._currentBranch] = [0, 0];
this.data.branchMap[this._currentBranch] = {
loc: node.loc,
};
}

newBranch(node, type) {
this._currentBranch++;
this.data.b[this._currentBranch] = [];
this.data.branchMap[this._currentBranch] = {
type,
loc: node.loc,
locations: [],
};
return this._currentBranch;
}

newBranchPath(index, node) {
const bMeta = this.data.branchMap[index];
const counts = this.data.b[index];

bMeta.locations.push(getLocation(node));
counts.push(0);
return counts.length - 1;
}
}

module.exports = TemplateCoverage;
Loading
Loading