Skip to content

Commit be80d99

Browse files
committed
feat(utils): add utility for rounding to max decimals, use in formatDuration
1 parent 42fa531 commit be80d99

File tree

8 files changed

+55
-26
lines changed

8 files changed

+55
-26
lines changed

packages/plugin-lighthouse/src/lib/runner/details/__snapshots__/critical-request-chain.type.unit.test.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ exports[`parseCriticalRequestChainToAuditDetails > should convert chains to basi
4747
{
4848
"name": "https://www.gstatic.com/devrel-devsite/prod/ve761bca974e16662f27aa8810df6d144acde5bdbeeca0dfd50e25f86621eaa19/chrome/css/app.css",
4949
"values": {
50-
"duration": "70.050 ms",
50+
"duration": "70.05 ms",
5151
"transferSize": "133.58 kB",
5252
},
5353
},

packages/plugin-lighthouse/src/lib/runner/details/item-value.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
formatBytes,
66
formatDuration,
77
html,
8+
roundDecimals,
89
truncateText,
910
ui,
1011
} from '@code-pushup/utils';
@@ -72,17 +73,14 @@ export function formatTableItemPropertyValue(
7273
return html.link(url);
7374
case 'timespanMs':
7475
case 'ms':
75-
return formatDuration(Number(parsedItemValue));
76+
return formatDuration(Number(parsedItemValue), 3);
7677
case 'node':
7778
return parseNodeValue(itemValue as Details.NodeValue);
7879
case 'source-location':
7980
return truncateText(String(parsedItemValue), 200);
8081
case 'numeric':
8182
const num = Number(parsedItemValue);
82-
if (num.toFixed(3).toString().endsWith('.000')) {
83-
return String(num);
84-
}
85-
return String(num.toFixed(3));
83+
return roundDecimals(num, 3).toString();
8684
case 'text':
8785
return truncateText(String(parsedItemValue), 500);
8886
case 'multi': // @TODO

packages/plugin-lighthouse/src/lib/runner/details/item-value.unit.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,13 @@ describe('formatTableItemPropertyValue', () => {
260260
{ type: 'numeric', value: 2142 },
261261
'timespanMs',
262262
),
263-
).toBe('2.14 s');
263+
).toBe('2.142 s');
264264
});
265265

266266
it('should format value based on itemValueFormat "ms"', () => {
267267
expect(
268268
formatTableItemPropertyValue({ type: 'numeric', value: 2142 }, 'ms'),
269-
).toBe('2.14 s');
269+
).toBe('2.142 s');
270270
});
271271

272272
it('should format value based on itemValueFormat "node"', () => {
@@ -318,7 +318,7 @@ describe('formatTableItemPropertyValue', () => {
318318
{ type: 'numeric', value: 42.1 } as Details.ItemValue,
319319
'numeric',
320320
),
321-
).toBe('42.100');
321+
).toBe('42.1');
322322
});
323323

324324
it('should format value based on itemValueFormat "numeric" as int if float has only 0 post comma', () => {

packages/utils/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export {
5353
formatDuration,
5454
pluralize,
5555
pluralizeToken,
56+
roundDecimals,
5657
slugify,
5758
truncateDescription,
5859
truncateIssueMessage,

packages/utils/src/lib/formatting.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import {
44
MAX_TITLE_LENGTH,
55
} from '@code-pushup/models';
66

7+
export function roundDecimals(value: number, maxDecimals: number) {
8+
const multiplier = Math.pow(10, maxDecimals);
9+
return Math.round(value * multiplier) / multiplier;
10+
}
11+
712
export function slugify(text: string): string {
813
return text
914
.trim()
@@ -40,20 +45,18 @@ export function formatBytes(bytes: number, decimals = 2) {
4045

4146
const i = Math.floor(Math.log(positiveBytes) / Math.log(k));
4247

43-
return `${Number.parseFloat((positiveBytes / Math.pow(k, i)).toFixed(dm))} ${
44-
sizes[i]
45-
}`;
48+
return `${roundDecimals(positiveBytes / Math.pow(k, i), dm)} ${sizes[i]}`;
4649
}
4750

4851
export function pluralizeToken(token: string, times: number): string {
4952
return `${times} ${Math.abs(times) === 1 ? token : pluralize(token)}`;
5053
}
5154

52-
export function formatDuration(duration: number, granularity = 0): string {
53-
if (duration < 1000) {
54-
return `${granularity ? duration.toFixed(granularity) : duration} ms`;
55+
export function formatDuration(ms: number, maxDecimals: number = 2): string {
56+
if (ms < 1000) {
57+
return `${roundDecimals(ms, maxDecimals)} ms`;
5558
}
56-
return `${(duration / 1000).toFixed(2)} s`;
59+
return `${roundDecimals(ms / 1000, maxDecimals)} s`;
5760
}
5861

5962
export function formatDate(date: Date): string {

packages/utils/src/lib/formatting.unit.test.ts

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,39 @@ import {
55
formatDuration,
66
pluralize,
77
pluralizeToken,
8+
roundDecimals,
89
slugify,
910
truncateText,
1011
} from './formatting.js';
1112

13+
describe('roundDecimals', () => {
14+
it('should remove extra decimals', () => {
15+
expect(roundDecimals(1.2345, 2)).toBe(1.23);
16+
});
17+
18+
it('should round last decimal', () => {
19+
expect(roundDecimals(123.456, 2)).toBe(123.46);
20+
});
21+
22+
it('should return number to prevent unnecessary trailing 0s in decimals', () => {
23+
const result = roundDecimals(42.500001, 3);
24+
expect(result).toBeTypeOf('number');
25+
expect(result.toString()).toBe('42.5');
26+
expect(result.toString()).not.toBe('42.50');
27+
});
28+
29+
it('should leave integers unchanged', () => {
30+
const value = 42;
31+
const result = roundDecimals(value, 3);
32+
expect(result).toBe(value);
33+
expect(result.toString()).toBe('42');
34+
});
35+
36+
it('should round to integer if max decimals set to 0', () => {
37+
expect(roundDecimals(100.5, 0)).toBe(101);
38+
});
39+
});
40+
1241
describe('slugify', () => {
1342
it.each([
1443
['Largest Contentful Paint', 'largest-contentful-paint'],
@@ -76,16 +105,14 @@ describe('formatDuration', () => {
76105
it.each([
77106
[-1, '-1 ms'],
78107
[0, '0 ms'],
79-
[1, '1 ms'],
80-
[2, '2 ms'],
81-
[1200, '1.20 s'],
82-
])('should log correctly formatted duration for %s', (ms, displayValue) => {
108+
[23, '23 ms'],
109+
[891, '891 ms'],
110+
[1200, '1.2 s'],
111+
[56789, '56.79 s'],
112+
[60_000, '60 s'],
113+
])('should format duration of %s milliseconds as %s', (ms, displayValue) => {
83114
expect(formatDuration(ms)).toBe(displayValue);
84115
});
85-
86-
it('should log formatted duration with 1 digit after the decimal point', () => {
87-
expect(formatDuration(120.255_555, 1)).toBe('120.3 ms');
88-
});
89116
});
90117

91118
describe('formatDate', () => {

packages/utils/src/lib/reports/__snapshots__/generate-md-report.unit.test.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Report was created by [Code PushUp](https://github.com/code-pushup/cli#readme) o
1111
1212
| Commit | Version | Duration | Plugins | Categories | Audits |
1313
| :----------------------------------------------------------- | :------: | -------: | :-----: | :--------: | :----: |
14-
| ci: update action (535b8e9e557336618a764f3fa45609d224a62837) | \`v1.0.0\` | 4.20 s | 1 | 3 | 3 |
14+
| ci: update action (535b8e9e557336618a764f3fa45609d224a62837) | \`v1.0.0\` | 4.2 s | 1 | 3 | 3 |
1515
"
1616
`;
1717

packages/utils/src/lib/reports/generate-md-report.unit.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ describe('aboutSection', () => {
601601
expect(md).toContainMarkdownTableRow([
602602
'ci: update action (535b8e9e557336618a764f3fa45609d224a62837)',
603603
'`v1.0.0`',
604-
'4.20 s',
604+
'4.2 s',
605605
'1',
606606
'3',
607607
'3',

0 commit comments

Comments
 (0)