blob: 7852664de7a6a11a92c3dcbe4e99e3157c86a7a3 [file] [edit]
#!/usr/bin/env node
/**
*
* Copyright (c) 2020 Silicon Labs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const scriptUtil = require('./script-util.js')
const fsExtra = require('fs-extra')
const env = require('../src-electron/util/env')
//workaround: executeCmd()/spawn() fails silently without complaining about missing path to electron
process.env.PATH = process.env.PATH + ':/usr/local/bin/'
/**
* Normalize coverage data structure
* @param {*} coverageData
* @returns normalized coverage data
*/
function normalizeCoverageData(coverageData) {
// If it has a 'data' wrapper (Jest format), extract it
if (coverageData.data && typeof coverageData.data === 'object') {
return coverageData.data
}
// Otherwise return as-is (Cypress format)
return coverageData
}
/**
* Check if coverage data is valid (has actual coverage info)
* @param {*} coverageData
* @returns boolean
*/
function isValidCoverageData(coverageData) {
if (!coverageData || typeof coverageData !== 'object') {
return false
}
// Check if it has at least one file with coverage data
const keys = Object.keys(coverageData)
return (
keys.length > 0 &&
keys.some(
(key) =>
coverageData[key] &&
typeof coverageData[key] === 'object' &&
'path' in coverageData[key]
)
)
}
/**
* Check coverage thresholds and fail if below 80%
* @param {string} coverageSummaryPath
*/
function checkCoverageThresholds(coverageSummaryPath) {
if (!fsExtra.existsSync(coverageSummaryPath)) {
console.error('āŒ Coverage summary not found')
process.exit(1)
}
const coverageSummary = fsExtra.readJsonSync(coverageSummaryPath)
const total = coverageSummary.total
const thresholds = {
lines: 80
}
let failed = false
console.log('\nšŸ“Š Coverage Summary:')
Object.keys(thresholds).forEach((key) => {
const actual = total[key].pct
const threshold = thresholds[key]
const status = actual >= threshold ? 'āœ…' : 'āŒ'
console.log(`${status} ${key}: ${actual}% (threshold: ${threshold}%)`)
if (actual < threshold) {
failed = true
}
})
if (failed) {
console.error('\nāŒ Coverage below 80% threshold. Please add more tests.')
process.exit(1)
} else {
console.log('\nāœ… All coverage thresholds passed!')
}
}
/**
* Execute the coverage report script.
*/
async function executeScript() {
try {
// Create directory if it does not exist
await fsExtra.ensureDir('.nyc_output')
let hasCoverage = false
let combinedCoverage = {}
if (fsExtra.existsSync('cypress-coverage/coverage-final.json')) {
const cypressData = await fsExtra.readJson(
'cypress-coverage/coverage-final.json'
)
const normalizedCypress = normalizeCoverageData(cypressData)
if (isValidCoverageData(normalizedCypress)) {
// Merge into combined coverage
Object.assign(combinedCoverage, normalizedCypress)
console.log('āœ… Cypress coverage found and processed')
hasCoverage = true
} else {
console.log(
'āš ļø Cypress coverage file found but contains no valid coverage data'
)
}
} else {
console.log(
'āš ļø No Cypress coverage file found at cypress-coverage/coverage-final.json'
)
}
if (fsExtra.existsSync('jest-coverage/coverage-final.json')) {
const jestData = await fsExtra.readJson(
'jest-coverage/coverage-final.json'
)
const normalizedJest = normalizeCoverageData(jestData)
if (isValidCoverageData(normalizedJest)) {
// Merge into combined coverage (Jest data will override Cypress if same files)
Object.assign(combinedCoverage, normalizedJest)
console.log('āœ… Jest coverage found and processed')
hasCoverage = true
} else {
console.log(
'āš ļø Jest coverage file found but contains no valid coverage data'
)
}
} else {
console.log(
'āš ļø No Jest coverage file found at jest-coverage/coverage-final.json'
)
}
if (!hasCoverage) {
console.log(
'āŒ No valid coverage data found to combine. Run tests first.'
)
return
}
// Validate that we have coverage data after combining
if (Object.keys(combinedCoverage).length === 0) {
console.log(
'āŒ No coverage data found after normalization and combination'
)
return
}
// Write the combined coverage directly to .nyc_output
await fsExtra.writeJson('.nyc_output/out.json', combinedCoverage, {
spaces: 2
})
console.log('āœ… Coverage files merged successfully')
// Generate final report with JSON summary for threshold checking
await scriptUtil.executeCmd(
{},
'npx',
'nyc report --reporter lcov --reporter text --reporter json-summary --report-dir coverage'.split(
' '
)
)
console.log(
`āœ… Combined coverage report generated at ./coverage/lcov-report/index.html`
)
// Check coverage thresholds - this will exit with code 1 if below 80%
checkCoverageThresholds('coverage/coverage-summary.json')
} catch (err) {
console.log('Error in generating reports:', err)
process.exit(1)
}
}
executeScript()