diff --git a/lib/converter/untested.js b/lib/converter/untested.js index 7f62137..64168e0 100644 --- a/lib/converter/untested.js +++ b/lib/converter/untested.js @@ -4,8 +4,10 @@ const Util = require('../utils/util.js'); const { pathToFileURL, fileURLToPath } = require('url'); +const { normalizeSourcePath, getSourcePathReplacer } = require('../utils/source-path.js'); + // const EC = require('eight-colors'); -const { minimatch } = require('../packages/monocart-coverage-vendor.js'); +const { minimatch, convertSourceMap } = require('../packages/monocart-coverage-vendor.js'); // ======================================================================================================== @@ -109,16 +111,64 @@ const resolveFileType = (fileType, filePath) => { return 'js'; }; -const getUntestedCoverageData = (emptyList, options, coverageType) => { +const saveUntestedFileSource = async (entryFile, options) => { + const { + id, + url, + source, + sourceMap + } = entryFile; + // console.log('-', entry.sourcePath); + + const { cachePath } = Util.getCacheFileInfo('source', id, options.cacheDir); + if (fs.existsSync(cachePath)) { + return; + } + + // save source and sourceMap to separated json file + const sourceData = { + id, + url, + source, + sourceMap + }; + + // remove comments if not debug + if (!Util.isDebug()) { + sourceData.source = convertSourceMap.removeComments(source); + } + + // console.log('save untested file', id, url); + + await Util.saveSourceCacheFile(sourceData, options); + +}; + +const getUntestedCoverageData = async (entryList, options, coverageType) => { + + // save all empty coverage + const dataId = Util.uid(); + const results = { + id: dataId + }; - // NOTE: do not save untested file to raw report + if (coverageType === 'istanbul') { + results.type = 'istanbul'; + results.data = {}; + } else { + results.type = 'v8'; + results.data = []; + } const emptyCoverageList = []; // save all empty source and sourcemap - for (const entryFile of emptyList) { + for (const entry of entryList) { + + // for raw report: source file + await saveUntestedFileSource(entry, options); - const { type, url } = entryFile; + const { type, url } = entry; if (coverageType === 'istanbul') { @@ -133,6 +183,7 @@ const getUntestedCoverageData = (emptyList, options, coverageType) => { b: {} }; // object + results.data[item.path] = item; emptyCoverageList.push(item); } else { @@ -140,59 +191,99 @@ const getUntestedCoverageData = (emptyList, options, coverageType) => { // =============================================== if (type === 'js') { // empty js - entryFile.functions = entryFile.functions || [{ + entry.functions = entry.functions || [{ functionName: '', ranges: [{ startOffset: 0, - endOffset: entryFile.source.length, + endOffset: entry.source.length, count: 0 }] }]; } else { // empty css - entryFile.ranges = entryFile.ranges || []; + entry.ranges = entry.ranges || []; } + const item = { + ... entry + }; + delete item.source; + delete item.sourceMap; + + // array + results.data.push(item); // will be parsed to AST and converted to V8 coverage - emptyCoverageList.push(entryFile); + emptyCoverageList.push(entry); } } + // for raw report: coverage file + const { cachePath } = Util.getCacheFileInfo('coverage', dataId, options.cacheDir); + await Util.writeFile(cachePath, JSON.stringify(results)); + return emptyCoverageList; }; -const getEmptyCoverages = async (fileList, options, coverageType, fileTransformer) => { +const getEmptyCoverages = async (testedMap, options, coverageType, fileList, fileTransformer) => { + const sourceFilter = Util.getSourceFilter(options); + const sourcePathReplacer = getSourcePathReplacer(options); + const baseDir = options.baseDir; - const emptyList = []; + // console.log(fileList); + const entryList = []; for (const item of fileList) { - const { - filePath, fileType, sourcePath - } = item; + + const { fileType, filePath } = item; const type = resolveFileType(fileType, filePath); const url = pathToFileURL(filePath).toString(); const source = Util.readFileSync(filePath); - const entryFile = { + const entry = { empty: true, type, url, - sourcePath, - // for empty, css supports both source and text source }; - await fileTransformer(entryFile, coverageType); + // normalize sourcePath here + let sourcePath = normalizeSourcePath(url, baseDir); + if (sourcePathReplacer) { + const newSourcePath = sourcePathReplacer(sourcePath, entry); + if (typeof newSourcePath === 'string' && newSourcePath) { + sourcePath = newSourcePath; + } + } + + // console.log(sourcePath); + + if (testedMap.has(sourcePath)) { + continue; + } + + if (!sourceFilter(sourcePath)) { + continue; + } + + entry.sourcePath = sourcePath; + await fileTransformer(entry, coverageType); // after transformer - entryFile.id = Util.calculateSha1(entryFile.sourcePath + entryFile.source); + entry.id = Util.calculateSha1(entry.sourcePath + entry.source); - emptyList.push(entryFile); + entryList.push(entry); } + + // console.log('fileList', fileList); + if (!entryList.length) { + return; + } + + // save empty coverage for merging raw reports - return getUntestedCoverageData(emptyList, options, coverageType); + return getUntestedCoverageData(entryList, options, coverageType); }; const getUntestedList = (testedMap, options, coverageType = 'v8') => { @@ -201,44 +292,34 @@ const getUntestedList = (testedMap, options, coverageType = 'v8') => { if (!allOptions) { return; } + const { dirList, fileFilter, fileTransformer } = allOptions; - const sourceFilter = Util.getSourceFilter(options); - const fileList = []; dirList.forEach((dir) => { Util.forEachFile(dir, [], (fileName, fileDir) => { const filePath = path.resolve(fileDir, fileName); // return file extname for file type const fileType = fileFilter(filePath); - if (!fileType) { - return; + if (fileType) { + fileList.push({ + filePath, + fileType, + fileDir, + fileName + }); } - const sourcePath = Util.relativePath(filePath); - if (testedMap.has(sourcePath)) { - return; - } - - if (!sourceFilter(sourcePath)) { - return; - } - - fileList.push({ - filePath, - fileType, - sourcePath - }); }); }); - // console.log('fileList', fileList); + if (!fileList.length) { return; } - return getEmptyCoverages(fileList, options, coverageType, fileTransformer); + return getEmptyCoverages(testedMap, options, coverageType, fileList, fileTransformer); }; diff --git a/lib/utils/util.js b/lib/utils/util.js index 3a25a40..be40d5d 100644 --- a/lib/utils/util.js +++ b/lib/utils/util.js @@ -165,6 +165,7 @@ const Util = { // eslint-disable-next-line complexity getEntryFilter: (options) => { + // for entry.url if (options.entryFilterHandler) { return options.entryFilterHandler; @@ -219,6 +220,7 @@ const Util = { // eslint-disable-next-line complexity getSourceFilter: (options) => { + // for sourcePath if (options.sourceFilterHandler) { return options.sourceFilterHandler; diff --git a/package-lock.json b/package-lock.json index a30936b..c20e919 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "monocart-coverage-reports", - "version": "2.10.6", + "version": "2.10.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "monocart-coverage-reports", - "version": "2.10.6", + "version": "2.10.7", "license": "MIT", "workspaces": [ "test" diff --git a/test/test-merge.js b/test/test-merge.js index 60ac391..ed8f7ae 100644 --- a/test/test-merge.js +++ b/test/test-merge.js @@ -24,7 +24,7 @@ const coverageOptions = { assetsPath: '../assets', // lcov: true, - all: ['test/mock/src', 'test/mock/node/lib'], + // all: ['test/mock/src', 'test/mock/node/lib'], sourcePath: (filePath) => { const list = ['monocart-coverage-reports/', 'coverage-v8/'];