diff --git a/packages/bundlecheck/src/__tests__/trend.test.ts b/packages/bundlecheck/src/__tests__/trend.test.ts index 01ec203c..b8354687 100644 --- a/packages/bundlecheck/src/__tests__/trend.test.ts +++ b/packages/bundlecheck/src/__tests__/trend.test.ts @@ -177,6 +177,52 @@ describe("renderTrendGraph", () => { ); }); + it("should use equal bar lengths when formatted values are the same", () => { + // These values differ by a few bytes but format to the same string + // 3295 bytes and 3297 bytes both format to "3.22 kB" + const results: TrendResult[] = [ + { version: "3.0.0", rawSize: 3297, gzipSize: 1650 }, + { version: "2.0.0", rawSize: 3296, gzipSize: 1649 }, + { version: "1.0.0", rawSize: 3295, gzipSize: 1648 }, + ]; + + const lines = renderTrendGraph("test-package", results, true); + + // Find gzip size lines (between "Gzip Size:" and "Raw Size:") + const gzipStartIdx = lines.findIndex((l) => l.includes("Gzip Size:")); + const rawStartIdx = lines.findIndex((l) => l.includes("Raw Size:")); + const gzipLines = lines + .slice(gzipStartIdx + 1, rawStartIdx) + .filter((l) => l.includes("▇")); + + // All bars should have the same number of bar characters + const barCounts = gzipLines.map((l) => (l.match(/▇/g) || []).length); + expect(new Set(barCounts).size).toBe(1); // All same length + expect(barCounts[0]).toBe(30); // Should be max bar width + }); + + it("should use different bar lengths when formatted values differ", () => { + // These values format to different strings + const results: TrendResult[] = [ + { version: "3.0.0", rawSize: 3000, gzipSize: 1500 }, + { version: "2.0.0", rawSize: 2000, gzipSize: 1000 }, + { version: "1.0.0", rawSize: 1000, gzipSize: 500 }, + ]; + + const lines = renderTrendGraph("test-package", results, true); + + // Find gzip size lines + const gzipStartIdx = lines.findIndex((l) => l.includes("Gzip Size:")); + const rawStartIdx = lines.findIndex((l) => l.includes("Raw Size:")); + const gzipLines = lines + .slice(gzipStartIdx + 1, rawStartIdx) + .filter((l) => l.includes("▇")); + + // Bars should have different lengths + const barCounts = gzipLines.map((l) => (l.match(/▇/g) || []).length); + expect(new Set(barCounts).size).toBeGreaterThan(1); // Different lengths + }); + it("should include bar characters", () => { const results: TrendResult[] = [ { version: "2.0.0", rawSize: 2048, gzipSize: 1024 }, diff --git a/packages/bundlecheck/src/trend.ts b/packages/bundlecheck/src/trend.ts index 8d1ae634..363f86be 100644 --- a/packages/bundlecheck/src/trend.ts +++ b/packages/bundlecheck/src/trend.ts @@ -106,6 +106,12 @@ export function renderTrendGraph( const minRawSize = Math.min(...rawSizes); const maxRawSize = Math.max(...rawSizes); + // Check if all formatted values are the same (to avoid misleading bar differences) + const formattedGzipSizes = results.map((r) => formatBytes(r.gzipSize)); + const formattedRawSizes = results.map((r) => formatBytes(r.rawSize)); + const allGzipSame = new Set(formattedGzipSizes).size === 1; + const allRawSame = new Set(formattedRawSizes).size === 1; + // Find max version length for alignment const maxVersionLen = Math.max(...results.map((r) => r.version.length)); @@ -114,9 +120,14 @@ export function renderTrendGraph( const minBarWidth = 10; // Minimum bar length for smallest value // Helper to calculate bar length with min-max scaling - const calcBarLength = (value: number, min: number, max: number): number => { - if (max === min) { - return barWidth; // All values are the same + const calcBarLength = ( + value: number, + min: number, + max: number, + allSame: boolean, + ): number => { + if (max === min || allSame) { + return barWidth; // All values are effectively the same } // Scale from minBarWidth to barWidth based on position between min and max const ratio = (value - min) / (max - min); @@ -132,7 +143,12 @@ export function renderTrendGraph( // Gzip size bars lines.push(blue("Gzip Size:")); for (const result of results) { - const barLength = calcBarLength(result.gzipSize, minGzipSize, maxGzipSize); + const barLength = calcBarLength( + result.gzipSize, + minGzipSize, + maxGzipSize, + allGzipSame, + ); const bar = "▇".repeat(barLength); const padding = " ".repeat(maxVersionLen - result.version.length); const sizeStr = formatBytes(result.gzipSize); @@ -144,7 +160,12 @@ export function renderTrendGraph( // Raw size bars lines.push(blue("Raw Size:")); for (const result of results) { - const barLength = calcBarLength(result.rawSize, minRawSize, maxRawSize); + const barLength = calcBarLength( + result.rawSize, + minRawSize, + maxRawSize, + allRawSame, + ); const bar = "▇".repeat(barLength); const padding = " ".repeat(maxVersionLen - result.version.length); const sizeStr = formatBytes(result.rawSize);