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
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,18 +201,22 @@ QUnit.done(async () => {
});
```

Under the hood, `ember-cli-code-coverage` creates a mapping of app and addon namespaces to their actual on disk locations. While in general this
works correctly in the rare execption you can customize this via:
Under the hood, `ember-cli-code-coverage` attempts to "de-namespacify" paths into their real on disk location inside of
`project.root` (ie give a namespaced path like lib/inrepo/components/foo.js would live in lib/inrepo/addon/components/foo.js). It makes
some assumptions (where files live in in-repo addons vs app code for example) and sometimes those assumptions might not hold. Passing a
function `modifyAssetLocation` will allow you to override where a file actually lives inside of your project. The returned string should
be relative to your project root.

```js
const app = new EmberApp(defaults, {
'ember-cli-code-coverage': {
namespaceOverride(item, namespace) {
if (item.name === 'common') {
namespace.set(item.name, 'some-full-path/addon');
namespace.set(path.join(item.name, 'test-support'), 'some-full-path/addon-test-support');
return true;
modifyAssetLocation(root, relativePath) {
// here is an example of saying that `component/foo.js` actually
// lives in `lib/common/app/foo.js` on disk.
if (fs.existsSync(path.join(root, 'lib/inrepo/app', relativePath))) {
return path.join('lib/common/app', relativePath);
}

return false;
},
},
Expand Down
25 changes: 11 additions & 14 deletions packages/ember-cli-code-coverage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,19 @@ module.exports = {
included(app) {
this._super.included.apply(this, arguments);
let config = app.options[this.name] || {};
this.namespaceOverride = config && config.namespaceOverride;
this.modifyAssetLocation = config && config.modifyAssetLocation;
},

buildNamespaceMappings(namespaceOverride) {
buildNamespaceMappings() {
let rootNamespaceMappings = new Map();
function recurse(item, namespaceOverride) {
let override = false;
if (namespaceOverride) {
override = namespaceOverride(item, rootNamespaceMappings);
}

if (item.isEmberCLIProject && item.isEmberCLIProject() && !override) {
function recurse(item) {
if (item.isEmberCLIProject && item.isEmberCLIProject()) {
let projectConfig = item.config(process.env.EMBER_ENV);
rootNamespaceMappings.set(
projectConfig.modulePrefix,
path.join(item.root, 'app')
);
} else if (item.treePaths && !override) {
} else if (item.treePaths) {
let addonPath = path.join(item.root, item.treePaths.addon);
let addonTestSupportPath = path.join(
item.root,
Expand All @@ -103,10 +98,10 @@ module.exports = {
addonTestSupportPath
);
}
item.addons.forEach((i) => recurse(i, namespaceOverride));
item.addons.forEach((i) => recurse(i));
}

recurse(this.project, namespaceOverride);
recurse(this.project);

// this adds a "default" lookup to the namespace in the event that there is no
// namespace. this comes up under embroider depending on the app structure of
Expand All @@ -130,7 +125,8 @@ module.exports = {
configPath: this.project.configPath(),
root: this.project.root,
fileLookup: this.fileLookup,
namespaceMappings: this.buildNamespaceMappings(this.namespaceOverride),
namespaceMappings: this.buildNamespaceMappings(),
modifyAssetLocation: this.modifyAssetLocation,
});
},

Expand All @@ -139,7 +135,8 @@ module.exports = {
configPath: this.project.configPath(),
root: this.project.root,
fileLookup: this.fileLookup,
namespaceMappings: this.buildNamespaceMappings(this.namespaceOverride),
namespaceMappings: this.buildNamespaceMappings(),
modifyAssetLocation: this.modifyAssetLocation,
};
// if we're running `ember test --server` use the `serverMiddleware`.
if (process.argv.includes('--server') || process.argv.includes('-s')) {
Expand Down
25 changes: 22 additions & 3 deletions packages/ember-cli-code-coverage/lib/attach-middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,12 @@ function normalizeRelativePath(root, filepath) {
* where as in Classic it will be the "actual" app like: `/Users/x/y/z/ember-test-app/ember-test-app/components/foo.js`
* both of these absolute paths should be converted into `app/components/foo.js`
*/
function adjustCoverageKey(root, filepath, namespaceMappings) {
function adjustCoverageKey(
root,
filepath,
namespaceMappings,
modifyAssetLocation
) {
let relativePath = path.relative(root, filepath);
let embroiderTmpPathRegex = /embroider\/.{6}/gm;

Expand All @@ -81,6 +86,19 @@ function adjustCoverageKey(root, filepath, namespaceMappings) {
pathWithoutNamespace = pathWithoutNamespace.slice(1);
}

if (modifyAssetLocation) {
let customPath = modifyAssetLocation(
root,
relativePath,
filepath,
namespaceMappings
);

if (customPath) {
return customPath;
}
}

if (namespaceMappings.has(namespaceKey)) {
return path.join(
...[namespaceMappings.get(namespaceKey), ...pathWithoutNamespace]
Expand All @@ -94,12 +112,13 @@ function adjustCoverageKey(root, filepath, namespaceMappings) {
}

function adjustCoverage(coverage, options) {
let { root, namespaceMappings } = options;
let { root, namespaceMappings, modifyAssetLocation } = options;
const adjustedCoverage = Object.keys(coverage).reduce((memo, filePath) => {
let relativeToProjectRoot = adjustCoverageKey(
root,
filePath,
namespaceMappings
namespaceMappings,
modifyAssetLocation
);
coverage[filePath].path = path.relative(root, relativeToProjectRoot);
memo[path.relative(root, relativeToProjectRoot)] = coverage[filePath];
Expand Down