UNPKG

3.15 kBJavaScriptView Raw
1#!/usr/bin/env node
2// usage: flow-coverage
3//
4// Run flow coverage on project.
5
6const childProcess = require('child_process')
7const flow = require('flow-bin')
8const fs = require('fs')
9const {join} = require('path')
10
11const execFile = (file, args) =>
12 new Promise((resolve, reject) => {
13 childProcess.execFile(
14 file,
15 args,
16 {
17 maxBuffer: Infinity
18 },
19 (error, stdout, stderr) => {
20 if (error) {
21 reject(error)
22 } else {
23 resolve({stdout, stderr})
24 }
25 }
26 )
27 })
28
29async function execFileJSON(file, args) {
30 args.push('--json')
31 const {stdout, stderr} = await execFile(file, args)
32 if (stderr) {
33 return JSON.parse(stderr)
34 } else {
35 return JSON.parse(stdout)
36 }
37}
38
39function computeCoverage(covered, uncovered) {
40 const total = covered + uncovered
41 if (total) {
42 return 100 * (covered / total)
43 } else {
44 return 100
45 }
46}
47
48async function getCoverage(path) {
49 const json = await execFileJSON(flow, ['coverage', path])
50 if (json && json.expressions) {
51 const uncoveredCount = json.expressions['uncovered_count']
52 const coveredCount = json.expressions['covered_count']
53 const covered = computeCoverage(coveredCount, uncoveredCount)
54 return {path, uncoveredCount, coveredCount, covered}
55 } else {
56 return {path, uncoveredCount: 0, coveredCount: 0, covered: 0}
57 }
58}
59
60async function startFlow() {
61 try {
62 await execFile(flow, ['start', '--wait'])
63 } catch (error) {
64 if (error.code === 11) {
65 /* already running */
66 } else {
67 throw error
68 }
69 }
70}
71
72// const ignore = [/\.flowconfig$/, /\.json$/, /\.test\.js$/, /\/__generated__\//, /\/flow-typed\//, /\/node_modules\//]
73//
74// async function flowList() {
75// execFile('git', ['grep', '--name-only', '--', '@flow'])
76//
77// const paths = await execFileJSON(flow, ['ls'])
78// return paths.filter(path => !ignore.some(re => re.test(path)))
79// }
80
81async function grepFlowFiles() {
82 const {stdout} = await execFile('git', ['grep', '--null', '--name-only', '--', '@flow'])
83 return stdout.split('\0').filter(path => path)
84}
85
86;(async function() {
87 let threshold = 0
88
89 const packageJsonPath = join(process.cwd(), 'package.json')
90 if (fs.existsSync(packageJsonPath)) {
91 const packageJson = require(packageJsonPath)
92 threshold = (packageJson.flow && packageJson.flow.coverageThreshold) || 0
93 }
94
95 await startFlow()
96
97 const files = await grepFlowFiles()
98
99 let totalCoveredCount = 0
100 let totalUncoveredCount = 0
101
102 for (const file of files) {
103 const {path, covered, coveredCount, uncoveredCount} = await getCoverage(file)
104 process.stdout.write(`${covered.toFixed()}\t${path}\n`)
105 totalCoveredCount += coveredCount
106 totalUncoveredCount += uncoveredCount
107 }
108
109 const totalCoverage = computeCoverage(totalCoveredCount, totalUncoveredCount)
110
111 process.stdout.write(`${totalCoverage.toFixed()}\t(total)\n`)
112 if (totalCoverage < threshold) {
113 process.stderr.write(`expected at least ${threshold}% coverage, but was ${totalCoverage.toFixed()}%\n`)
114 process.exit(1)
115 }
116})().catch(error => {
117 process.stderr.write(`${error}\n`)
118 process.exit(2)
119})