Skip to content
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
135 changes: 81 additions & 54 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ var attachMiddleware = require('./lib/attach-middleware');
var config = require('./lib/config');
const walkSync = require('walk-sync');
const VersionChecker = require('ember-cli-version-checker');
const concat = require('lodash.concat');

function requireBabelPlugin(pluginName) {
let plugin = require(pluginName);
Expand All @@ -22,6 +23,12 @@ function requireBabelPlugin(pluginName) {
return plugin;
}

function getPlugins(appOrAddon) {
let options = appOrAddon.options = appOrAddon.options || {};
options.babel = options.babel || {};
return options.babel.plugins = options.babel.plugins || [];
}

// Regular expression to extract the file extension from a path.
const EXT_RE = /\.[^\.]+$/;

Expand All @@ -45,11 +52,19 @@ module.exports = {
let checker = new VersionChecker(this.parent).for('ember-cli-babel', 'npm');

if (checker.satisfies('>= 6.0.0')) {
this.IstanbulPlugin = requireBabelPlugin('babel-plugin-istanbul');
const IstanbulPlugin = requireBabelPlugin('babel-plugin-istanbul');
const exclude = this._getExcludes();
const include = this._getIncludes();

concat(
this.app,
this._findCoveredAddon(),
this._findInRepoAddons()
)
.filter(Boolean)
.map(getPlugins)
.forEach((plugins) => plugins.push([IstanbulPlugin, { exclude, include }]));

this._instrumentAppDirectory();
this._instrumentAddonDirectory();
this._instrumentInRepoAddonDirectories();
} else {
this.project.ui.writeWarnLine(
'ember-cli-code-coverage: You are using an unsupported ember-cli-babel version,' +
Expand Down Expand Up @@ -96,76 +111,71 @@ module.exports = {
// Custom Methods

/**
* Instrument the "app" directory.
* Thin wrapper around exists-sync that allows easy stubbing in tests
* @param {String} path - path to check existence of
* @returns {Boolean} whether or not path exists
*/
_instrumentAppDirectory() {
const dir = path.join(this.project.root, 'app');
let prefix = this.parent.isEmberCLIAddon() ? 'dummy' : this.parent.name();
this._instrumentDirectory(this.app, dir, prefix);
_existsSync: function(path) {
return existsSync(path);
},

/**
* Instrument the "addon" directory.
* Get project configuration
* @returns {Configuration} project configuration
*/
_instrumentAddonDirectory() {
let addon = this._findCoveredAddon();
if (addon) {
const dir = path.join(this.project.root, 'addon');
this._instrumentDirectory(addon, dir, addon.name);
}
_getConfig: function() {
return config(this.project.configPath());
},

/**
* Instrument the in-repo-addon directories in "lib/*".
* Get paths to include for coverage
* @returns {Array<String>} include paths
*/
_instrumentInRepoAddonDirectories() {
const pkg = this.project.pkg;
if (pkg['ember-addon'] && pkg['ember-addon'].paths) {
pkg['ember-addon'].paths.forEach((addonPath) => {
let addonName = path.basename(addonPath);
let addonDir = path.join(this.project.root, addonPath);
let addon = this.project.findAddonByName(addonName);
let addonAppDir = path.join(addonDir, 'app');
let addonAddonDir = path.join(addonDir, 'addon');
this._instrumentDirectory(this.app, addonAppDir, this.parent.name());
this._instrumentDirectory(addon, addonAddonDir, addonName);
});
}
_getIncludes: function() {
return concat(
this._getIncludesForAppDirectory(),
this._getIncludesForAddonDirectory(),
this._getIncludesForInRepoAddonDirectories()
).filter(Boolean);
},

/**
* Instrument directory helper.
* @param {Object} appOrAddon The Ember app or addon config.
* @param {String} dir The path to the Ember app or addon.
* @param {String} modulePrefix The prefix to the ember module ('app', 'dummy' or the name of the addon).
* Get paths to include for covering the "app" directory.
* @returns {Array<String>} include paths
*/
_instrumentDirectory(appOrAddon, dir, modulePrefix) {
if (existsSync(dir)) {
let options = appOrAddon.options = appOrAddon.options || {};
options.babel = options.babel || {};
let plugins = options.babel.plugins = options.babel.plugins || [];
plugins.push([this.IstanbulPlugin, {
exclude: this._getExcludes(),
include: this._getIncludes(dir, modulePrefix)
}]);
}
_getIncludesForAppDirectory: function() {
const dir = path.join(this.project.root, 'app');
let prefix = this.parent.isEmberCLIAddon() ? 'dummy' : this.parent.name();
return this._getIncludesForDir(dir, prefix);
},

/**
* Thin wrapper around exists-sync that allows easy stubbing in tests
* @param {String} path - path to check existence of
* @returns {Boolean} whether or not path exists
* Get paths to include for covering the "addon" directory.
* @returns {Array<String>} include paths
*/
_existsSync: function(path) {
return existsSync(path);
_getIncludesForAddonDirectory: function() {
let addon = this._findCoveredAddon();
if (addon) {
const dir = path.join(this.project.root, 'addon');
return this._getIncludesForDir(dir, addon.name);
}
},

/**
* Get project configuration
* @returns {Configuration} project configuration
* Get paths to include for covering the in-repo-addon directories in "lib/*".
* @returns {Array<String>} include paths
*/
_getConfig: function() {
return config(this.project.configPath());
_getIncludesForInRepoAddonDirectories: function() {
return this._findInRepoAddons().reduce((acc, addon) => {
let addonDir = path.join(this.project.root, 'lib', addon.name);
let addonAppDir = path.join(addonDir, 'app');
let addonAddonDir = path.join(addonDir, 'addon');
return concat(
acc,
this._getIncludesForDir(addonAppDir, this.parent.name()),
this._getIncludesForDir(addonAddonDir, addon.name)
);
}, []);
},

/**
Expand All @@ -174,7 +184,7 @@ module.exports = {
* @param {String} prefix The prefix to the ember module ('app', 'dummy' or the name of the addon).
* @returns {Array<String>} include paths
*/
_getIncludes: function(dir, prefix) {
_getIncludesForDir: function(dir, prefix) {
let dirname = path.relative(this.project.root, dir);
let globs = this.registry.extensionsForType('js').map((extension) => `**/*.${extension}`);

Expand Down Expand Up @@ -229,5 +239,22 @@ module.exports = {
}

return this._coveredAddon;
},

/**
* Find the app's in-repo addons (if any).
* @returns {Array<Addon>} the in-repo addons
*/
_findInRepoAddons: function() {
if (!this._inRepoAddons) {
const pkg = this.project.pkg;
const inRepoAddonPaths = pkg['ember-addon'] && pkg['ember-addon'].paths;
this._inRepoAddons = (inRepoAddonPaths || []).map((addonPath) => {
let addonName = path.basename(addonPath);
return this.project.findAddonByName(addonName);
});
}

return this._inRepoAddons;
}
};
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@
"babel-plugin-istanbul": "^4.1.5",
"babel-plugin-transform-async-to-generator": "^6.24.1",
"body-parser": "^1.15.0",
"co": "^4.6.0",
"ember-cli-babel": "^6.6.0",
"ember-cli-htmlbars": "^2.0.1",
"ember-cli-version-checker": "^2.0.0",
"exists-sync": "0.0.4",
"extend": "^3.0.0",
"fs-extra": "^5.0.0",
"istanbul-api": "^1.1.14",
"lodash.concat": "^4.5.0",
"node-dir": "^0.1.16",
"rsvp": "^4.8.1",
"walk-sync": "^0.3.2"
Expand Down Expand Up @@ -66,6 +68,7 @@
"ember-try": "^0.2.23",
"eslint-plugin-ember": "^5.0.0",
"eslint-plugin-node": "^5.2.1",
"fixturify": "^0.3.4",
"glob": "^7.1.2",
"lerna-changelog": "^0.7.0",
"loader.js": "^4.2.3",
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/my-addon/app/utils/my-covered-util.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { default } from '../../addon/utils/my-covered-util';
export { default } from 'my-addon/utils/my-covered-util';
2 changes: 1 addition & 1 deletion test/fixtures/my-addon/app/utils/my-uncovered-util.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { default } from '../../addon/utils/my-uncovered-util';
export { default } from 'my-addon/utils/my-uncovered-util';

42 changes: 42 additions & 0 deletions test/fixtures/my-app-with-in-repo-addon/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module.exports = {
root: true,
parserOptions: {
ecmaVersion: 2017,
sourceType: 'module'
},
extends: [
'eslint:recommended'
],
env: {
browser: true
},
rules: {
},
overrides: [
// node files
{
files: [
'index.js',
'testem.js',
'ember-cli-build.js',
'config/**/*.js',
'test/**',
'tests/dummy/config/**/*.js'
],
excludedFiles: [
'app/**',
'addon/**',
'test/fixtures/**',
'tests/dummy/app/**'
],
parserOptions: {
sourceType: 'script',
ecmaVersion: 2015
},
env: {
browser: false,
node: true
}
}
]
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function myCoveredUtil() {
return true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function myUncoveredUtil() {
return true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function myCoveredUtil() {
return true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function myUncoveredUtil() {
return true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'my-in-repo-addon/utils/my-covered-util';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from 'my-in-repo-addon/utils/my-uncovered-util';

24 changes: 24 additions & 0 deletions test/fixtures/my-app-with-in-repo-addon/testem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module.exports = {
test_page: 'tests/index.html?hidepassed',
disable_watching: true,
launch_in_ci: [
'Chrome'
],
launch_in_dev: [
'Chrome'
],
browser_args: {
Chrome: {
mode: 'ci',
args: [
// --no-sandbox is needed when running Chrome inside a container
process.env.TRAVIS ? '--no-sandbox' : null,

'--disable-gpu',
'--headless',
'--remote-debugging-port=0',
'--window-size=1440,900'
].filter(Boolean)
}
}
};
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import myCoveredUtil from 'my-in-repo-addon/utils/my-covered-util';
import { module, test } from 'qunit';

module('Unit | Utility | my covered util');

// Replace this with your real tests.
test('it works', function(assert) {
let result = myCoveredUtil();
assert.ok(result);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import myCoveredUtil from 'my-app-with-in-repo-addon/utils/my-covered-util-app';
import { module, test } from 'qunit';

module('Unit | Utility | my covered util app');

// Replace this with your real tests.
test('it works', function(assert) {
let result = myCoveredUtil();
assert.ok(result);
});
Loading