diff --git a/.circleci/config.yml b/.circleci/config.yml index b90df468..d4182b2e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -122,6 +122,12 @@ workflows: - run: command: npx nyc report --check-coverage true --lines 100 working_directory: examples/before-each-visit + - run: + name: Check code coverage 📈 + command: | + node ../../scripts/check-coverage main.js + node ../../scripts/only-covered main.js + working_directory: examples/before-each-visit - cypress/run: attach-workspace: true @@ -145,6 +151,12 @@ workflows: - run: command: npx nyc report --check-coverage true --lines 100 working_directory: examples/before-all-visit + - run: + name: Check code coverage 📈 + command: | + node ../../scripts/check-coverage main.js + node ../../scripts/only-covered main.js + working_directory: examples/before-all-visit - cypress/run: attach-workspace: true @@ -168,6 +180,13 @@ workflows: command: npm run coverage:check working_directory: examples/ts-example + - run: + name: Check code coverage 📈 + command: | + node ../../scripts/check-coverage main.ts + node ../../scripts/only-covered main.ts + working_directory: examples/ts-example + - cypress/run: attach-workspace: true name: example-same-folder @@ -194,6 +213,13 @@ workflows: - run: command: npx nyc report --check-coverage true --lines 100 --include unit-utils.js working_directory: examples/same-folder + - run: + name: Check code coverage 📈 + command: | + node ../../scripts/check-coverage main.js + node ../../scripts/check-coverage unit-utils.js + node ../../scripts/only-covered main.js unit-utils.js + working_directory: examples/same-folder - publish: filters: diff --git a/scripts/check-coverage.js b/scripts/check-coverage.js new file mode 100644 index 00000000..4ff6bad1 --- /dev/null +++ b/scripts/check-coverage.js @@ -0,0 +1,47 @@ +const { join } = require('path') + +const filename = process.argv[2] +if (!filename) { + console.error('Usage: node %s ', __filename) + process.exit(1) +} +const coverageFilename = join(process.cwd(), '.nyc_output', 'out.json') +const coverage = require(coverageFilename) +const fileCoverageKey = Object.keys(coverage).find(name => { + const fileCover = coverage[name] + if (fileCover.path.endsWith(filename)) { + return fileCover + } +}) + +if (!fileCoverageKey) { + console.error( + 'Could not find file %s in coverage in file %s', + filename, + coverageFilename + ) + process.exit(1) +} + +const fileCoverage = coverage[fileCoverageKey] +const statementCounters = fileCoverage.s +const isThereUncoveredStatement = Object.keys(statementCounters).some( + (k, key) => { + return statementCounters[key] === 0 + } +) +if (isThereUncoveredStatement) { + console.error( + 'file %s has statements that were not covered by tests', + fileCoverage.path + ) + console.log('statement counters %o', statementCounters) + + process.exit(1) +} + +console.log( + '✅ All statements in file %s (found for %s) were covered', + fileCoverage.path, + filename +) diff --git a/scripts/only-covered.js b/scripts/only-covered.js new file mode 100644 index 00000000..073d397f --- /dev/null +++ b/scripts/only-covered.js @@ -0,0 +1,51 @@ +const { join } = require('path') +const _ = require('lodash') + +const filenames = process.argv.slice(2) +if (!filenames.length) { + console.error('Usage: node %s ', __filename) + process.exit(1) +} + +const shouldBeCovered = filepath => + filenames.some(name => filepath.endsWith(name)) + +const coverageFilename = join(process.cwd(), '.nyc_output', 'out.json') +const coverage = require(coverageFilename) + +const coveredFilepaths = Object.keys(coverage).map(name => coverage[name].path) + +// console.log(coveredFilepaths) + +const [covered, extraCoveredFiles] = _.partition( + coveredFilepaths, + shouldBeCovered +) + +if (extraCoveredFiles.length) { + console.error('Error: found extra covered files 🔥') + console.error('Expected the following files in coverage results') + console.error(filenames.join('\n')) + console.error('extra files covered 🔥') + console.error(extraCoveredFiles.join('\n')) + process.exit(1) +} + +if (covered.length < filenames.length) { + console.error('Error: expected all files from the list to be covered 🔥') + console.error('Expected the following files in coverage results') + console.error(filenames.join('\n')) + console.error('But found only these files to be covered') + console.error(covered.join('\n')) + + console.error('Files missing from the coverage 🔥') + const missingFiles = filenames.filter( + filename => + !covered.some(coveredFilename => coveredFilename.endsWith(filename)) + ) + console.error(missingFiles.join('\n')) + + process.exit(1) +} + +console.log('✅ All and only expected files were covered')