From 4a1229b344dd859fb39a908c2f55951d1543156d Mon Sep 17 00:00:00 2001 From: Max P Date: Fri, 16 Aug 2024 12:01:45 +0200 Subject: [PATCH] Add test coverage config and badges Configured Jest for improved test coverage reporting and threshold enforcement. Updated README with project time and test coverage badges. Added scripts to fix coverage report paths and generate badges. Updated dependencies to include necessary tools for coverage reporting. Bumped package version to 0.0.9. --- README.md | 13 ++++++++ jest.config.coverage.cjs | 28 +++++++++++++++++ package-lock.json | 52 ++++++++++++++++++++++++++++++-- package.json | 5 +++- scripts/fix-coverage-paths.cjs | 46 ++++++++++++++++++++++++++++ scripts/generate-badge.cjs | 55 ++++++++++++++++++++++++++++++++++ 6 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 jest.config.coverage.cjs create mode 100644 scripts/fix-coverage-paths.cjs create mode 100644 scripts/generate-badge.cjs diff --git a/README.md b/README.md index 580509f..1da8f0d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,16 @@ +### Project Time + +![Time](https://waka.mpassarello.de/api/badge/MaxP/interval:any/project:TSinjex?label=Project%20time) + +### Test Coverage + +[Coverage Report..](https://pxammaxp.github.io/TSinjex/coverage/lcov-report/index.html) + +| Statements | Branches | Functions | Lines | +| --------------------------- | ----------------------- | ------------------------- | ----------------- | +| ![Statements](https://pxammaxp.github.io/TSinjex/coverage/badges/badge-statements.svg) | ![Branches](https://pxammaxp.github.io/TSinjex/coverage/badges/badge-branches.svg) | ![Functions](https://pxammaxp.github.io/TSinjex/coverage/badges/badge-functions.svg) | ![Lines](https://pxammaxp.github.io/TSinjex/coverage/badges/badge-lines.svg) | + + # TSinjex ## Configuration diff --git a/jest.config.coverage.cjs b/jest.config.coverage.cjs new file mode 100644 index 0000000..df0c2a9 --- /dev/null +++ b/jest.config.coverage.cjs @@ -0,0 +1,28 @@ +module.exports = { + setupFilesAfterEnv: ['./scripts/jest.setup.js'], + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/__tests__/**/*.test.ts', '**/?(*.)+(test).ts'], + testPathIgnorePatterns: ['\\.spec\\.ts$', '\\.performance\\.test\\.ts$'], + moduleDirectories: ['node_modules', 'src'], + moduleNameMapper: { + '^src/(.*)$': '/src/$1', + }, + collectCoverage: true, + coverageDirectory: '.locale/coverage', + coverageReporters: ['text', ['lcov', { projectRoot: '..' }], 'json-summary'], + collectCoverageFrom: [ + 'src/**/*.{ts,tsx}', + '!src/**/*.d.ts', + '!src/**/*.performance.test.ts', + '!src/auto-imports.ts' + ], + coverageThreshold: { + global: { + branches: 70, + functions: 70, + lines: 70, + statements: 70, + }, + }, +}; diff --git a/package-lock.json b/package-lock.json index 2b843f7..747f529 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ts-injex", - "version": "0.0.8", + "version": "0.0.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ts-injex", - "version": "0.0.8", + "version": "0.0.9", "license": "MIT", "dependencies": { "eslint-plugin-prettier": "^5.2.1", @@ -18,10 +18,12 @@ "@types/node": "^20.14.11", "@typescript-eslint/eslint-plugin": "^8.1.0", "@typescript-eslint/parser": "^8.1.0", + "axios": "^1.7.2", "eslint-plugin-deprecation": "^3.0.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsdoc": "^50.2.2", "eslint-plugin-override": "https://github.com/PxaMMaxP/eslint-plugin-override", + "istanbul-badges-readme": "^1.9.0", "jest": "^29.7.0", "ts-jest": "^29.2.3", "typedoc": "^0.26.5", @@ -2023,6 +2025,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -3592,6 +3605,26 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "peer": true }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -4361,6 +4394,15 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, + "node_modules/istanbul-badges-readme": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/istanbul-badges-readme/-/istanbul-badges-readme-1.9.0.tgz", + "integrity": "sha512-sD9lTsFajcfK07euJReQ0C9dy0VmXViMDJk67EZseGRC+jv+esxt5I3Viqoi1b43m5in5ek5b+0rpxJi41bJVw==", + "dev": true, + "bin": { + "istanbul-badges-readme": "lib/index.js" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -5843,6 +5885,12 @@ "node": ">= 6" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", diff --git a/package.json b/package.json index 197a864..f0d38f3 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "lint:fix": "eslint --fix --ext .ts .", "test:file": "jest --watch --onlyChanged --coverage=true --verbose", "test:verbose": "jest --verbose", + "test:coverage": "jest --config jest.config.coverage.cjs --coverage || true && node scripts/fix-coverage-paths.cjs && node scripts/generate-badge.cjs", "version:show": "node -e \"console.log(require('./package.json').version)\"", "docs": "typedoc" }, @@ -34,7 +35,9 @@ "eslint-plugin-override": "https://github.com/PxaMMaxP/eslint-plugin-override", "jest": "^29.7.0", "ts-jest": "^29.2.3", - "typedoc": "^0.26.5" + "typedoc": "^0.26.5", + "istanbul-badges-readme": "^1.9.0", + "axios": "^1.7.2" }, "dependencies": { "eslint-plugin-prettier": "^5.2.1", diff --git a/scripts/fix-coverage-paths.cjs b/scripts/fix-coverage-paths.cjs new file mode 100644 index 0000000..090f4c4 --- /dev/null +++ b/scripts/fix-coverage-paths.cjs @@ -0,0 +1,46 @@ +const fs = require('fs'); +const path = require('path'); + +const coverageDir = path.join(__dirname, '..', '.locale', 'coverage'); +const typedocUrl = 'https://pxammaxp.github.io/TSinjex/'; + +const getAllFiles = (dir, files = []) => { + fs.readdirSync(dir).forEach(file => { + const fullPath = path.join(dir, file); + if (fs.statSync(fullPath).isDirectory()) { + getAllFiles(fullPath, files); + } else { + files.push(fullPath); + } + }); + return files; +}; + +// Alle HTML-Dateien im coverage-Ordner finden +const htmlFiles = getAllFiles(coverageDir).filter(file => file.endsWith('.html')); + +// Alle HTML-Dateien bearbeiten +htmlFiles.forEach(filePath => { + fs.readFile(filePath, 'utf8', (err, data) => { + if (err) { + console.error(`Error reading file ${filePath}:`, err); + return; + } + + // Relative Pfade anpassen + let fixedData = data.replace(/(src|href)="(?!\.)/g, '$1="./'); + + // Link zur TypeDoc-Dokumentation hinzufügen + const linkHtml = `
Zur TypeDoc-Dokumentation
`; + fixedData = fixedData.replace('', `${linkHtml}`); + + fs.writeFile(filePath, fixedData, 'utf8', (err) => { + if (err) { + console.error(`Error writing file ${filePath}:`, err); + return; + } + + console.log(`Fixed paths and added link in ${filePath}`); + }); + }); +}); diff --git a/scripts/generate-badge.cjs b/scripts/generate-badge.cjs new file mode 100644 index 0000000..f307d4c --- /dev/null +++ b/scripts/generate-badge.cjs @@ -0,0 +1,55 @@ +const fs = require('fs'); +const path = require('path'); +const { exec } = require('child_process'); +const axios = require('axios'); + +// Step 1: Create README.md in the coverage directory +const coverageReadmePath = path.join(__dirname, '..', '.locale', 'coverage', 'README.md'); +const readmeContent = ` +![Statements](#statements#) +![Branches](#branches#) +![Functions](#functions#) +![Lines](#lines#) +`; + +fs.writeFileSync(coverageReadmePath, readmeContent, 'utf8'); + +// Step 2: Execute the istanbul-badges-readme tool +exec('npx istanbul-badges-readme --coverageDir=./.locale/coverage --readmeDir=./.locale/coverage', (err, stdout, stderr) => { + if (err) { + console.error(`Error executing istanbul-badges-readme: ${stderr}`); + return; + } + console.log('Badges generated successfully.'); + + // Step 3: Extract the badge links from README.md + const updatedReadmeContent = fs.readFileSync(coverageReadmePath, 'utf8'); + const badgeLines = updatedReadmeContent.split('\n').filter(line => line.includes('https://img.shields.io')); + + // Ensure the target directory exists + const badgesDir = path.join(__dirname, '..', '.locale', 'coverage', 'badges'); + if (!fs.existsSync(badgesDir)) { + fs.mkdirSync(badgesDir, { recursive: true }); + } + + // Badge types and their order + const badgeTypes = ['statements', 'branches', 'functions', 'lines']; + + // Save the badge images + badgeLines.forEach(async (line, index) => { + const match = line.match(/\((https:\/\/img\.shields\.io\/badge\/[^)]+)\)/); + if (match) { + const url = match[1]; + const response = await axios.get(url, { responseType: 'arraybuffer' }); + const buffer = Buffer.from(response.data, 'binary'); + const fileName = `badge-${badgeTypes[index]}.svg`; + const filePath = path.join(badgesDir, fileName); + fs.writeFileSync(filePath, buffer); + console.log(`Saved ${fileName}`); + } + }); + + // Step 4: Delete the README.md file + fs.unlinkSync(coverageReadmePath); + console.log('README.md file deleted.'); +});