Skip to content

Commit

Permalink
feat: support for instrumenting files outside of current working dire…
Browse files Browse the repository at this point in the history
…ctory
  • Loading branch information
j03m authored May 25, 2020
1 parent 6b8e752 commit 7e53a0e
Show file tree
Hide file tree
Showing 17 changed files with 356 additions and 78 deletions.
5 changes: 3 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export declare class Report {
wrapperLength?: number,
resolve?: string,
all?: boolean,
src?: Array<string>,
allowExternal: boolean
})

run(): Promise<void>;
}
}
4 changes: 3 additions & 1 deletion lib/commands/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ exports.outputReport = async function (argv) {
resolve: argv.resolve,
omitRelative: argv.omitRelative,
wrapperLength: argv.wrapperLength,
all: argv.all
all: argv.all,
allowExternal: argv.allowExternal,
src: argv.src
})
await report.run()
if (argv.checkCoverage) await checkCoverages(argv, report)
Expand Down
12 changes: 12 additions & 0 deletions lib/parse-args.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ function buildYargs (withCommands = false) {
describe: 'supplying --all will cause c8 to consider all src files in the current working directory ' +
'when the determining coverage. Respects include/exclude.'
})
.options('allowExternal', {
default: false,
type: 'boolean',
describe: 'supplying --allowExternal will cause c8 to allow files from outside of your cwd. This applies both to' +
'files discovered in coverage temp files and also src files discovered if using the --all flag.'
})
.options('src', {
default: undefined,
type: 'string',
describe: 'supplying --src will override cwd as the default location where --all looks for src files. --src can be ' +
'supplied multiple times and each directory will be included. This allows for workspaces spanning multiple projects'
})
.pkgConf('c8')
.config(config)
.demandCommand(1)
Expand Down
71 changes: 43 additions & 28 deletions lib/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ class Report {
omitRelative,
wrapperLength,
resolve: resolvePaths,
all
all,
src,
allowExternal = false
}) {
this.reporter = reporter
this.reportsDirectory = reportsDirectory
Expand All @@ -30,13 +32,24 @@ class Report {
this.resolve = resolvePaths
this.exclude = new Exclude({
exclude: exclude,
include: include
include: include,
relativePath: !allowExternal
})
this.omitRelative = omitRelative
this.sourceMapCache = {}
this.wrapperLength = wrapperLength
this.all = all
this.src = process.cwd()
this.src = this._getSrc(src)
}

_getSrc (src) {
if (typeof src === 'string') {
return [src]
} else if (Array.isArray(src)) {
return src
} else {
return [process.cwd()]
}
}

async run () {
Expand Down Expand Up @@ -159,33 +172,35 @@ class Report {
v8ProcessCovs.unshift({
result: emptyReports
})
const workingDir = process.cwd()
this.exclude.globSync(workingDir).forEach((f) => {
const fullPath = resolve(workingDir, f)
if (!fileIndex.has(fullPath)) {
const ext = extname(f)
if (ext === '.js' || ext === '.ts' || ext === '.mjs') {
const stat = statSync(f)
const sourceMap = getSourceMapFromFile(f)
if (sourceMap !== undefined) {
this.sourceMapCache[`file://${fullPath}`] = { data: JSON.parse(readFileSync(sourceMap).toString()) }
const workingDirs = this.src
for (const workingDir of workingDirs) {
this.exclude.globSync(workingDir).forEach((f) => {
const fullPath = resolve(workingDir, f)
if (!fileIndex.has(fullPath)) {
const ext = extname(fullPath)
if (ext === '.js' || ext === '.ts' || ext === '.mjs') {
const stat = statSync(fullPath)
const sourceMap = getSourceMapFromFile(fullPath)
if (sourceMap !== undefined) {
this.sourceMapCache[`file://${fullPath}`] = { data: JSON.parse(readFileSync(sourceMap).toString()) }
}
emptyReports.push({
scriptId: 0,
url: resolve(fullPath),
functions: [{
functionName: '(empty-report)',
ranges: [{
startOffset: 0,
endOffset: stat.size,
count: 0
}],
isBlockCoverage: true
}]
})
}
emptyReports.push({
scriptId: 0,
url: resolve(f),
functions: [{
functionName: '(empty-report)',
ranges: [{
startOffset: 0,
endOffset: stat.size,
count: 0
}],
isBlockCoverage: true
}]
})
}
}
})
})
}
}

return mergeProcessCovs(v8ProcessCovs)
Expand Down
4 changes: 2 additions & 2 deletions lib/source-map-from-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ function getSourceMapFromFile (file) {
if (results !== null) {
const sourceMap = results[results.length - 1].split('=')[1]
if (isAbsolute(sourceMap)) {
return sourceMap
return sourceMap.trim()
} else {
const base = dirname(file)
return join(base, sourceMap)
return join(base, sourceMap).trim()
}
}
}
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/multidir1/file1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("hi")
1 change: 1 addition & 0 deletions test/fixtures/multidir2/file2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("hi")
1 change: 1 addition & 0 deletions test/fixtures/report/allowExternal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require("../multidir1/file1")
12 changes: 12 additions & 0 deletions test/fixtures/report/report-multi-dir-external.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const Report = require('../../../lib/report')
const report = new Report({
include: ['**/*.js'],
exclude: [],
reporter: ['text'],
tempDirectory: './temp',
omitRelative: true,
all: true,
src: ['../multidir1/', '../multidir2/'],
allowExternal: true
})
report.run()
12 changes: 12 additions & 0 deletions test/fixtures/report/report-single-dir-external.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const Report = require('../../../lib/report')
const report = new Report({
include: ['**/*.js'],
exclude: [],
reporter: ['text'],
tempDirectory: './temp',
omitRelative: true,
all: true,
src: '../multidir1/',
allowExternal: true
})
report.run()
1 change: 1 addition & 0 deletions test/fixtures/report/srcOverride.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('hihi')
1 change: 1 addition & 0 deletions test/fixtures/report/temp/coverage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result":[]}
10 changes: 10 additions & 0 deletions test/fixtures/source-maps/padded.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"use strict";
exports.__esModule = true;
var loaded_1 = require("./loaded");
console.log(loaded_1["default"](0));
console.log(loaded_1["default"](1));
console.log(loaded_1["default"](-1));
//# sourceMappingURL=padded.js.map


//ew extra whitespace ^
80 changes: 75 additions & 5 deletions test/integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { readFileSync } = require('fs')
const { resolve } = require('path')
const { spawnSync } = require('child_process')
const { statSync } = require('fs')
const { dirname } = require('path')
const c8Path = require.resolve('../bin/c8')
const nodePath = process.execPath
const tsNodePath = './node_modules/.bin/ts-node'
Expand Down Expand Up @@ -96,6 +97,53 @@ describe('c8', () => {
stderr.toString().should.match(/Cannot find module 'unknown'/u)
})

it('should allow for files outside of cwd', () => {
// Here we nest this test into the report directory making the multidir
// directories outside of cwd. If the `--allowExternal` flag is not provided
// the multidir files will now show up in the file report, even though they were
// required in
const { output, status } = spawnSync(nodePath, [
c8Path,
'--exclude="test/*.js"',
'--temp-directory=tmp/allowExternal',
'--clean=true',
'--allowExternal',
'--reporter=text',
nodePath,
require.resolve('./fixtures/report/allowExternal.js')
], {
cwd: dirname(require.resolve('./fixtures/report/allowExternal.js'))
})
status.should.equal(0)
output.toString('utf8').should.matchSnapshot()
})

it('should allow for multiple overrides of src location for --all', () => {
// Here we nest this test into the report directory making the multidir
// directories outside of cwd. Note, that the target srcOverride does not
// require fiels from these directories but we want them initialized to 0
// via --all. As such we --allowExternal and provide multiple --src patterns
// to override cwd.
const { output, status } = spawnSync(nodePath, [
c8Path,
'--exclude="test/*.js"',
'--temp-directory=../tmp/src',
'--clean=true',
'--allowExternal',
'--reporter=text',
'--all',
`--src=${dirname(require.resolve('./fixtures/multidir1/file1.js'))}`,
`--src=${dirname(require.resolve('./fixtures/multidir2/file2.js'))}`,
`--src=${dirname(require.resolve('./fixtures/report/srcOverride.js'))}`,
nodePath,
require.resolve('./fixtures/report/srcOverride.js')
], {
cwd: dirname(require.resolve('./fixtures/report/srcOverride.js'))
})
status.should.equal(0)
output.toString('utf8').should.matchSnapshot()
})

describe('check-coverage', () => {
before(() => {
spawnSync(nodePath, [
Expand All @@ -112,10 +160,10 @@ describe('c8', () => {
const { output, status } = spawnSync(nodePath, [
c8Path,
'check-coverage',
'--exclude="test/*.js"',
'--exclude="test/fixtures/*.js"',
'--temp-directory=tmp/check-coverage',
'--lines=70',
'--branches=60',
'--branches=56',
'--statements=70'
])
status.should.equal(0)
Expand Down Expand Up @@ -168,7 +216,7 @@ describe('c8', () => {
spawnSync(nodePath, [
c8Path,
'--exclude="test/*.js"',
'--temp-directory=tmp/report',
'--temp-directory=./tmp/report',
'--clean=false',
nodePath,
require.resolve('./fixtures/normal')
Expand All @@ -180,7 +228,7 @@ describe('c8', () => {
c8Path,
'report',
'--exclude="test/*.js"',
'--temp-directory=tmp/report',
'--temp-directory=./tmp/report',
'--clean=false'
])
output.toString('utf8').should.matchSnapshot()
Expand Down Expand Up @@ -431,7 +479,6 @@ describe('c8', () => {
output.toString('utf8').should.matchSnapshot()
})
})

// see: https://github.com/bcoe/c8/issues/149
it('cobertura report escapes special characters', () => {
spawnSync(nodePath, [
Expand All @@ -449,4 +496,27 @@ describe('c8', () => {
.replace(/\\/g, '/')
cobertura.toString('utf8').should.matchSnapshot()
})
describe('report', () => {
it('supports reporting on directories outside cwd', () => {
// invoke a script that uses report as an api and supplies src dirs out
// of cwd
const { output } = spawnSync(nodePath, [
require.resolve('./fixtures/report/report-multi-dir-external.js')
], {
cwd: dirname(require.resolve('./fixtures/report/report-multi-dir-external.js'))
})
output.toString('utf8').should.matchSnapshot()
})

it('supports reporting on single directories outside cwd', () => {
// invoke a script that uses report as an api and supplies src dirs out
// of cwd.
const { output } = spawnSync(nodePath, [
require.resolve('./fixtures/report/report-single-dir-external.js')
], {
cwd: dirname(require.resolve('./fixtures/report/report-single-dir-external.js'))
})
output.toString('utf8').should.matchSnapshot()
})
})
})
Loading

0 comments on commit 7e53a0e

Please sign in to comment.