From 33cfda822166faef245ae74a3307c0455691b3d5 Mon Sep 17 00:00:00 2001 From: Robin Date: Tue, 16 Nov 2021 17:58:49 +0100 Subject: [PATCH 1/2] Add failing test for files in app directory of in-repo addons --- .../__snapshots__/in-repo-addon-test.js.snap | 96 +++++++++++++++++-- .../my-in-repo-addon-app-covered-util.js | 3 + .../my-in-repo-addon-app-covered-util-test.js | 10 ++ 3 files changed, 100 insertions(+), 9 deletions(-) create mode 100644 test-packages/my-app-with-in-repo-addon/lib/my-in-repo-addon/app/utils/my-in-repo-addon-app-covered-util.js create mode 100644 test-packages/my-app-with-in-repo-addon/tests/unit/utils/my-in-repo-addon-app-covered-util-test.js diff --git a/test-packages/__snapshots__/in-repo-addon-test.js.snap b/test-packages/__snapshots__/in-repo-addon-test.js.snap index 5d02209f..3346f738 100644 --- a/test-packages/__snapshots__/in-repo-addon-test.js.snap +++ b/test-packages/__snapshots__/in-repo-addon-test.js.snap @@ -236,6 +236,84 @@ Object { "total": 1, }, }, + "lib/my-in-repo-addon/app/utils/my-covered-util.js": Object { + "branches": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + "functions": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + "lines": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + "statements": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + }, + "lib/my-in-repo-addon/app/utils/my-in-repo-addon-app-covered-util.js": Object { + "branches": Object { + "covered": 0, + "pct": 100, + "skipped": 0, + "total": 0, + }, + "functions": Object { + "covered": 1, + "pct": 100, + "skipped": 0, + "total": 1, + }, + "lines": Object { + "covered": 1, + "pct": 100, + "skipped": 0, + "total": 1, + }, + "statements": Object { + "covered": 1, + "pct": 100, + "skipped": 0, + "total": 1, + }, + }, + "lib/my-in-repo-addon/app/utils/my-uncovered-util.js": Object { + "branches": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + "functions": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + "lines": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + "statements": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + }, "total": Object { "branches": Object { "covered": 0, @@ -244,22 +322,22 @@ Object { "total": 2, }, "functions": Object { - "covered": 3, - "pct": 33.33, + "covered": 4, + "pct": 40, "skipped": 0, - "total": 9, + "total": 10, }, "lines": Object { - "covered": 8, - "pct": 47.06, + "covered": 9, + "pct": 50, "skipped": 0, - "total": 17, + "total": 18, }, "statements": Object { - "covered": 8, - "pct": 47.06, + "covered": 9, + "pct": 50, "skipped": 0, - "total": 17, + "total": 18, }, }, } diff --git a/test-packages/my-app-with-in-repo-addon/lib/my-in-repo-addon/app/utils/my-in-repo-addon-app-covered-util.js b/test-packages/my-app-with-in-repo-addon/lib/my-in-repo-addon/app/utils/my-in-repo-addon-app-covered-util.js new file mode 100644 index 00000000..cbcd1ef9 --- /dev/null +++ b/test-packages/my-app-with-in-repo-addon/lib/my-in-repo-addon/app/utils/my-in-repo-addon-app-covered-util.js @@ -0,0 +1,3 @@ +export default function myInRepoAddonAppCoveredUtil() { + return true; +} diff --git a/test-packages/my-app-with-in-repo-addon/tests/unit/utils/my-in-repo-addon-app-covered-util-test.js b/test-packages/my-app-with-in-repo-addon/tests/unit/utils/my-in-repo-addon-app-covered-util-test.js new file mode 100644 index 00000000..9ab890e4 --- /dev/null +++ b/test-packages/my-app-with-in-repo-addon/tests/unit/utils/my-in-repo-addon-app-covered-util-test.js @@ -0,0 +1,10 @@ +import myInRepoAddonAppCoveredUtil from 'my-app-with-in-repo-addon/utils/my-in-repo-addon-app-covered-util'; +import { module, test } from 'qunit'; + +module('Unit | Utility | my in repo addon app covered util'); + +// Replace this with your real tests. +test('it works', function(assert) { + let result = myInRepoAddonAppCoveredUtil(); + assert.ok(result); +}); From abdd695ac8e8b2ff4d64a964b57889f78ce77be3 Mon Sep 17 00:00:00 2001 From: Robin Date: Thu, 18 Nov 2021 11:19:07 +0100 Subject: [PATCH 2/2] Fix no coverage reported for files in app directory of in-repo addons --- .../lib/attach-middleware.js | 103 +++++++++++++----- .../custom-path-in-repo-addon-test.js.snap | 52 +++++++++ test-packages/attach-middleware-test.js | 18 +-- 3 files changed, 135 insertions(+), 38 deletions(-) diff --git a/packages/ember-cli-code-coverage/lib/attach-middleware.js b/packages/ember-cli-code-coverage/lib/attach-middleware.js index a45401f2..4ba0fad2 100644 --- a/packages/ember-cli-code-coverage/lib/attach-middleware.js +++ b/packages/ember-cli-code-coverage/lib/attach-middleware.js @@ -16,6 +16,17 @@ function logError(err, req, res, next) { next(err); } +function getInRepoPaths(root) { + let pkgJSONPath = path.join(root, 'package.json'); + + if (fs.existsSync(pkgJSONPath)) { + let pkgJSON = fs.readJsonSync(path.join(root, 'package.json')); + return (pkgJSON['ember-addon'] && pkgJSON['ember-addon']['paths']) || []; + } + + return []; +} + /* * This function normalizes the relativePath to match what we get from a classical app. Its goal * is to change any in repo paths like: app-namespace/lib/in-repo-namespace/components/foo.js to @@ -24,29 +35,24 @@ function logError(err, req, res, next) { function normalizeRelativePath(root, filepath) { let embroiderTmpPathRegex = /embroider\/.{6}/gm; let relativePath = filepath.split(embroiderTmpPathRegex)[1].slice(1); - - if (fs.existsSync(path.join(root, 'package.json'))) { - let pkgJSON = fs.readJsonSync(path.join(root, 'package.json')); - let inRepoPaths = - (pkgJSON['ember-addon'] && pkgJSON['ember-addon']['paths']) || []; - - for (let i = 0; i <= inRepoPaths.length; i++) { - // this regex checks that the relative path is: app-namespace/path/to/inrepo - let inRepoPathRegex = new RegExp('[^/]+/' + inRepoPaths[i], 'gi'); - if (inRepoPathRegex.test(relativePath)) { - relativePath = path.join( - inRepoPaths[i].split(path.sep).slice(-1)[0], - filepath.split(inRepoPaths[i])[1] - ); - break; - } else if (relativePath.startsWith(inRepoPaths[i])) { - // this checks if relative path is: /path/to/inrepo - relativePath = path.join( - inRepoPaths[i].split(path.sep).slice(-1)[0], - filepath.split(inRepoPaths[i])[1] - ); - break; - } + let inRepoPaths = getInRepoPaths(root); + + for (let inRepoPath of inRepoPaths) { + // this regex checks that the relative path is: app-namespace/path/to/inrepo + let inRepoPathRegex = new RegExp('[^/]+/' + inRepoPath, 'gi'); + if (inRepoPathRegex.test(relativePath)) { + relativePath = path.join( + inRepoPath.split(path.sep).slice(-1)[0], + filepath.split(inRepoPath)[1] + ); + break; + } else if (relativePath.startsWith(inRepoPath)) { + // this checks if relative path is: /path/to/inrepo + relativePath = path.join( + inRepoPath.split(path.sep).slice(-1)[0], + filepath.split(inRepoPath)[1] + ); + break; } } @@ -62,7 +68,7 @@ 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, inRepoPaths) { let relativePath = path.relative(root, filepath); let embroiderTmpPathRegex = /embroider\/.{6}/gm; @@ -82,9 +88,16 @@ function adjustCoverageKey(root, filepath, namespaceMappings) { } if (namespaceMappings.has(namespaceKey)) { - return path.join( - ...[namespaceMappings.get(namespaceKey), ...pathWithoutNamespace] - ); + let namespaceValue = namespaceMappings.get(namespaceKey); + let inRepoPath = + namespaceValue.endsWith('app') && + inRepoPathForApp(root, relativePath, pathWithoutNamespace, inRepoPaths); + + if (inRepoPath) { + return inRepoPath; + } + + return path.join(...[namespaceValue, ...pathWithoutNamespace]); } // use the default key which will point to project root. this should only @@ -95,20 +108,50 @@ function adjustCoverageKey(root, filepath, namespaceMappings) { function adjustCoverage(coverage, options) { let { root, namespaceMappings } = options; + let inRepoPaths = getInRepoPaths(root); + const adjustedCoverage = Object.keys(coverage).reduce((memo, filePath) => { let relativeToProjectRoot = adjustCoverageKey( root, filePath, - namespaceMappings + namespaceMappings, + inRepoPaths ); - coverage[filePath].path = path.relative(root, relativeToProjectRoot); - memo[path.relative(root, relativeToProjectRoot)] = coverage[filePath]; + + let relativePath = path.relative(root, relativeToProjectRoot); + + coverage[filePath].path = relativePath; + memo[relativePath] = coverage[filePath]; return memo; }, {}); return adjustedCoverage; } +function inRepoPathForApp( + root, + relativePath, + pathWithoutNamespace, + inRepoPaths +) { + if (inRepoPaths.length === 0) return; + + if (fs.existsSync(path.join(root, 'app', ...pathWithoutNamespace))) return; + + for (let inRepoPath of inRepoPaths) { + let possibleAppPath = path.join( + root, + inRepoPath, + 'app', + ...pathWithoutNamespace + ); + + if (fs.existsSync(possibleAppPath)) { + return possibleAppPath; + } + } +} + function writeCoverage(coverage, options, map) { let { root } = options; const adjustedCoverage = adjustCoverage(coverage, options); diff --git a/test-packages/__snapshots__/custom-path-in-repo-addon-test.js.snap b/test-packages/__snapshots__/custom-path-in-repo-addon-test.js.snap index fa61c183..6a2192c2 100644 --- a/test-packages/__snapshots__/custom-path-in-repo-addon-test.js.snap +++ b/test-packages/__snapshots__/custom-path-in-repo-addon-test.js.snap @@ -184,6 +184,58 @@ Object { "total": 1, }, }, + "local-lib/addons/my-in-repo-addon/app/utils/my-covered-util.js": Object { + "branches": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + "functions": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + "lines": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + "statements": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + }, + "local-lib/addons/my-in-repo-addon/app/utils/my-uncovered-util.js": Object { + "branches": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + "functions": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + "lines": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + "statements": Object { + "covered": 0, + "pct": 0, + "skipped": 0, + "total": 0, + }, + }, "total": Object { "branches": Object { "covered": 0, diff --git a/test-packages/attach-middleware-test.js b/test-packages/attach-middleware-test.js index 672824e1..4e156b39 100644 --- a/test-packages/attach-middleware-test.js +++ b/test-packages/attach-middleware-test.js @@ -40,17 +40,18 @@ describe('attach-middleware', () => { ['hello', 'lib/hello/addon'], ['hello/test-support', 'lib/hello/addon-test-support'], ]); + let inRepoPaths = ['lib/hello']; - expect(adjustCoverageKey(root, path.join(root, 'app-namespace/app.js'), namespaceMappings)) + expect(adjustCoverageKey(root, path.join(root, 'app-namespace/app.js'), namespaceMappings, inRepoPaths)) .toEqual('app/app.js'); - expect(adjustCoverageKey(root, path.join(root, 'app-namespace/components/foo.js'), namespaceMappings)) + expect(adjustCoverageKey(root, path.join(root, 'app-namespace/components/foo.js'), namespaceMappings, inRepoPaths)) .toEqual('app/components/foo.js'); - expect(adjustCoverageKey(root, path.join(root, 'hello/components/foo.js'), namespaceMappings)) + expect(adjustCoverageKey(root, path.join(root, 'hello/components/foo.js'), namespaceMappings, inRepoPaths)) .toEqual('lib/hello/addon/components/foo.js'); - expect(adjustCoverageKey(root, path.join(root, 'hello/test-support/foo.js'), namespaceMappings)) + expect(adjustCoverageKey(root, path.join(root, 'hello/test-support/foo.js'), namespaceMappings, inRepoPaths)) .toEqual('lib/hello/addon-test-support/foo.js'); }); @@ -62,17 +63,18 @@ describe('attach-middleware', () => { ['hello', 'lib/hello/addon'], ['hello/test-support', 'lib/hello/addon-test-support'], ]); + let inRepoPaths = ['lib/hello']; - expect(adjustCoverageKey(root, path.join(root, 'addon-namespace/components/foo.js'), namespaceMappings)) + expect(adjustCoverageKey(root, path.join(root, 'addon-namespace/components/foo.js'), namespaceMappings, inRepoPaths)) .toEqual('addon/components/foo.js'); - expect(adjustCoverageKey(root, path.join(root, 'addon-namespace/test-support/foo.js'), namespaceMappings)) + expect(adjustCoverageKey(root, path.join(root, 'addon-namespace/test-support/foo.js'), namespaceMappings, inRepoPaths)) .toEqual('addon-test-support/foo.js'); - expect(adjustCoverageKey(root, path.join(root, 'hello/components/foo.js'), namespaceMappings)) + expect(adjustCoverageKey(root, path.join(root, 'hello/components/foo.js'), namespaceMappings, inRepoPaths)) .toEqual('lib/hello/addon/components/foo.js'); - expect(adjustCoverageKey(root, path.join(root, 'hello/test-support/foo.js'), namespaceMappings)) + expect(adjustCoverageKey(root, path.join(root, 'hello/test-support/foo.js'), namespaceMappings, inRepoPaths)) .toEqual('lib/hello/addon-test-support/foo.js'); }); });