diff --git a/README.md b/README.md index d5434fe8..9b3bcc7c 100644 --- a/README.md +++ b/README.md @@ -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; }, }, diff --git a/packages/ember-cli-code-coverage/index.js b/packages/ember-cli-code-coverage/index.js index 3cb4a6e7..35918811 100644 --- a/packages/ember-cli-code-coverage/index.js +++ b/packages/ember-cli-code-coverage/index.js @@ -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, @@ -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 @@ -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, }); }, @@ -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')) { diff --git a/packages/ember-cli-code-coverage/lib/attach-middleware.js b/packages/ember-cli-code-coverage/lib/attach-middleware.js index a45401f2..39b0887c 100644 --- a/packages/ember-cli-code-coverage/lib/attach-middleware.js +++ b/packages/ember-cli-code-coverage/lib/attach-middleware.js @@ -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; @@ -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] @@ -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];