From b1da2a6b371d90c480d60e861d5853d98019f815 Mon Sep 17 00:00:00 2001 From: Nico Meyer Date: Thu, 2 May 2024 20:47:59 +0200 Subject: [PATCH 1/3] feat: color config --- README.md | 3 +++ src/editor.ts | 34 +++++++++++++++++++++++---- src/helpers.ts | 29 +++++++++++++++++++++++ tests/editor.spec.ts | 56 ++++++++++++++++++++++++++++++++++---------- 4 files changed, 104 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 6eaee4c..b913e88 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,9 @@ npm run istanbul-badges-readme --logo="jest" ``` +#### Configure Badge Color + + #### Exit code - To exit with **1** code on validation errors (eg.: _README doesn't exist_, or _coverage directory doesn't exist_) or on editing errors (eg.: cannot write to README due to lack of permissions). The default exit code is **0**. Set a different one by using **--exitCode** argument. diff --git a/src/editor.ts b/src/editor.ts index 3f6d245..99ec3c5 100644 --- a/src/editor.ts +++ b/src/editor.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import { getArgumentValue } from './arguments'; import { readmePathConst, coveragePathConst, hashesConst, coverageUrlConst, badgeStyles } from './constants'; -import { getCoveragePath, getReadmePath, readFileAsync } from './helpers'; +import { getCoveragePath, getReadmePath, readFileAsync, parseColorConfig } from './helpers'; import { logger } from './logger'; import { Colors, Hashes, Report } from './types'; @@ -23,17 +23,40 @@ export const getReadmeHashes = (readmeFile: string): Hashes[] => { return filteredHashes as unknown as Hashes[]; }; -export const getCoverageColor = (coverage: number): Colors => { - if (coverage < 80) { + + +/** + * Determines the color representation of code coverage based on coverage percentage. + * Optionally uses a provided string to configure custom color thresholds. + * + * @param {number} coverage - The code coverage percentage to evaluate. + * @param {string | false} colorConfigString - A string to configure custom color thresholds, or false to use defaults. + * @returns {Colors} - The color associated with the given code coverage percentage, based on either default or custom thresholds. + */ +export const getCoverageColor = (coverage: number, colorConfigString?: string | false): Colors => { + const defaultThresholds = { + red: 80, + yellow: 90, + }; + + let colorThresholds = defaultThresholds; + + if (colorConfigString) { + colorThresholds = parseColorConfig(colorConfigString); + } + + // Adjusting to use dynamic color thresholds from colorConfigString if provided + if (coverage < colorThresholds.red) { return 'red'; } - if (coverage < 90) { + if (coverage < colorThresholds.yellow) { return 'yellow'; } return 'brightgreen'; }; + export const getCoverageBadge = (coverageFile: string, hashKey: string): string | boolean => { logInfo(`- Getting coverage badge url for ${hashKey}...`); @@ -45,7 +68,8 @@ export const getCoverageBadge = (coverageFile: string, hashKey: string): string } const coverage: number = parsedCoverage.total[hashKey].pct; - const color = getCoverageColor(coverage); + const customColors = getArgumentValue('colors'); + const color = getCoverageColor(coverage, customColors); const customLabel = getArgumentValue(`${hashKey}Label`); const customBadgeStyle = getArgumentValue('style'); const customBadgeLogo = getArgumentValue('logo'); diff --git a/src/helpers.ts b/src/helpers.ts index 37c1ea5..45b59cb 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -49,3 +49,32 @@ export const getExitCodeOnError = (): number | undefined => { return argExitCode && !isNaN(argExitCode) ? argExitCode : undefined; }; + +/** + * Parses a string representing colors and their corresponding numeric values into an object. + * The input string should be formatted as "color:value", with multiple color-value pairs separated by commas. + * This function specifically expects "red", "yellow", and "brightgreen" as the only valid colors in the string. + * + * @param {string} colorsString - The string representation of colors and their values to parse. + * @returns {{ red: number; yellow: number; brightgreen: number }} An object with keys "red", "yellow", and "brightgreen", + * each mapped to their numeric value as specified in the input string. + */ +export const parseColorConfig = (colorsString: string): { + red: number; + yellow: number; +} => { + if (!colorsString) { + return { red: 80, yellow: 90 }; + } + + return colorsString.split(',').reduce((acc, colorPair) => { + const [color, value] = colorPair.split(':'); + if (color === 'red' || color === 'yellow') { + acc[color] = parseInt(value, 10); + } + return acc; + }, {} as { red: number; yellow: number; }); +}; + + + diff --git a/tests/editor.spec.ts b/tests/editor.spec.ts index 8c5c214..d6e2071 100644 --- a/tests/editor.spec.ts +++ b/tests/editor.spec.ts @@ -1,6 +1,7 @@ import fs from 'fs'; import path from 'path'; -import { getReadmeHashes, getCoverageColor, getCoverageBadge, getNewReadme, writeNewReadme } from '../src/editor'; +import { getReadmeHashes, getCoverageBadge, getCoverageColor, getNewReadme, writeNewReadme } from '../src/editor'; +import { parseColorConfig } from '../src/helpers'; describe('Tests editor', () => { afterEach(() => { @@ -14,20 +15,49 @@ describe('Tests editor', () => { expect(readmeHashes.length).toEqual(0); }); - it('should getCoverageColor from both red, yellow and green', () => { - const colorsMap: Record = { - 90: 'brightgreen', - 80: 'yellow', - default: 'red', - }; + describe('parseColorConfig', () => { + it('correctly parses a valid color configuration string', () => { + const inputString = 'red:70,yellow:85'; + const expectedResult = { red: 70, yellow: 85 }; + expect(parseColorConfig(inputString)).toEqual(expectedResult); + }); + + it('ignores invalid color names', () => { + const inputString = 'red:70,yellow:85,blue:95'; + const expectedResult = { red: 70, yellow: 85 }; + expect(parseColorConfig(inputString)).toEqual(expectedResult); + }); + + it('returns default colors for an empty string', () => { + const inputString = ''; + const expectedResult = { red: 80, yellow: 90 }; + expect(parseColorConfig(inputString)).toEqual(expectedResult); + }); + }); - const checkColor = (threshold: number) => - expect(getCoverageColor(threshold)).toEqual(colorsMap[threshold] ? colorsMap[threshold] : colorsMap.default); + describe('getCoverageColor', () => { + test.each` + coverage | expectedColor + ${75} | ${'red'} + ${85} | ${'yellow'} + ${95} | ${'brightgreen'} + `( + 'returns $expectedColor for a coverage of $coverage using default thresholds', + ({ coverage, expectedColor }) => { + expect(getCoverageColor(coverage)).toBe(expectedColor); + } + ); - checkColor(90); - checkColor(80); - checkColor(79); - checkColor(10); + test('uses custom thresholds if provided', () => { + const customConfig = 'red:70,yellow:85'; + expect(getCoverageColor(65, customConfig)).toBe('red'); + expect(getCoverageColor(75, customConfig)).toBe('yellow'); + expect(getCoverageColor(90, customConfig)).toBe('brightgreen'); + }); + + test('returns brightgreen for coverage above 100', () => { + expect(getCoverageColor(105)).toBe('brightgreen'); + }); }); it('should getCoverageBadge from coverageFile', () => { From 8fe3db0a95ca43f4d50fe5b0481aee1e3d58b1ff Mon Sep 17 00:00:00 2001 From: Nico Meyer Date: Thu, 2 May 2024 20:48:38 +0200 Subject: [PATCH 2/3] docs: color config --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index b913e88..4a7e678 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,10 @@ ``` #### Configure Badge Color +- You can configure the color threshold of the badges by passing the `--colors` parameter. If you want red badges for a code coverage below 50% and yellow badges for a coverage below 60%, you'd do this: +```bash + npm run istanbul-badges-readme --colors=red:50,yellow:60 +``` #### Exit code From 4174c4334457536952a6a9688a9d5a7fa5c3f2b8 Mon Sep 17 00:00:00 2001 From: Nico Meyer Date: Thu, 2 May 2024 20:50:54 +0200 Subject: [PATCH 3/3] fix: typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a7e678..ee1109d 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ ``` #### Configure Badge Color -- You can configure the color threshold of the badges by passing the `--colors` parameter. If you want red badges for a code coverage below 50% and yellow badges for a coverage below 60%, you'd do this: +- You can configure the color threshold of the badges by passing the `--colors` argument. If you want red badges for a code coverage below 50% and yellow badges for a coverage below 60%, you'd do this: ```bash npm run istanbul-badges-readme --colors=red:50,yellow:60 ```