Skip to content

Commit c726356

Browse files
authored
Use explicit optional locale arg in math functions, rework tests accordingly (#2155)
use an explicit locale arg in math functions, rework tests accordingly
1 parent e2b0a7d commit c726356

File tree

3 files changed

+39
-45
lines changed

3 files changed

+39
-45
lines changed

app/util/math.spec.ts

+10-36
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,9 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8-
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
9-
10-
import {
11-
displayBigNum,
12-
nearest10,
13-
percentage,
14-
round,
15-
splitDecimal,
16-
toEngNotation,
17-
} from './math'
8+
import { describe, expect, it } from 'vitest'
9+
10+
import { displayBigNum, nearest10, percentage, round, splitDecimal } from './math'
1811
import { GiB } from './units'
1912

2013
function roundTest() {
@@ -119,15 +112,6 @@ describe('with default locale', () => {
119112
})
120113

121114
describe('with de-DE locale', () => {
122-
const originalLanguage = global.navigator.language
123-
124-
beforeAll(() => {
125-
Object.defineProperty(global.navigator, 'language', {
126-
value: 'de-DE',
127-
writable: true,
128-
})
129-
})
130-
131115
it.each([
132116
[0.23, ['0', ',23']],
133117
[0.236, ['0', ',24']],
@@ -150,17 +134,14 @@ describe('with de-DE locale', () => {
150134
[-50.2, ['-50', ',2']], // should correctly not round down to -51
151135
[1000.5, ['1.000', ',5']], // test localeString grouping
152136
])('splitDecimal %d -> %s', (input, output) => {
153-
expect(splitDecimal(input)).toEqual(output)
137+
expect(splitDecimal(input, 'de-DE')).toEqual(output)
154138
})
155139

156-
// rounding must work the same irrespective of locale
157-
it('round', roundTest)
158-
159140
it.each([
160141
[0n, ['0', false]],
161142
[1n, ['1', false]],
162143
[155n, ['155', false]],
163-
[999999n, ['999,999', false]],
144+
[999999n, ['999.999', false]],
164145
[1000000n, ['1 Mio.', true]],
165146
[1234567n, ['1,2 Mio.', true]],
166147
[9999999n, ['10 Mio.', true]], // note non-breaking space
@@ -169,14 +150,7 @@ describe('with de-DE locale', () => {
169150
[1293859032098219, ['1,3e15', true]],
170151
[23094304823948203952304920342n, ['23,1e27', true]],
171152
])('displayBigNum %d -> %s', (input, output) => {
172-
expect(displayBigNum(input)).toEqual(output)
173-
})
174-
175-
afterAll(() => {
176-
Object.defineProperty(global.navigator, 'language', {
177-
value: originalLanguage,
178-
writable: true,
179-
})
153+
expect(displayBigNum(input, 'de-DE')).toEqual(output)
180154
})
181155
})
182156

@@ -195,8 +169,8 @@ it.each([
195169
['en-CA'],
196170
['en-IN'],
197171
['ko-KR'],
198-
])('toEngNotation dots %s', (locale) => {
199-
expect(toEngNotation(n, locale)).toEqual('23.1e27')
172+
])('displayBigNum dots %s', (locale) => {
173+
expect(displayBigNum(n, locale)).toEqual(['23.1e27', true])
200174
})
201175

202176
it.each([
@@ -212,8 +186,8 @@ it.each([
212186
['tr-TR'],
213187
['pt-PT'],
214188
// ['ar-SA'], // saudi arabia, arabic script
215-
])('toEngNotation commas %s', (locale) => {
216-
expect(toEngNotation(n, locale)).toEqual('23,1e27')
189+
])('displayBigNum commas %s', (locale) => {
190+
expect(displayBigNum(n, locale)).toEqual(['23,1e27', true])
217191
})
218192

219193
it.each([

app/util/math.ts

+11-9
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import { splitOnceBy } from './array'
1616
* minus sign, group separators [comma in en-US], and of course actual number
1717
* groups). Those will get joined and the decimal part will be the empty string.
1818
*/
19-
export function splitDecimal(value: number): [string, string] {
20-
const nf = Intl.NumberFormat(navigator.language, { maximumFractionDigits: 2 })
19+
export function splitDecimal(value: number, locale?: string): [string, string] {
20+
const nf = Intl.NumberFormat(locale, { maximumFractionDigits: 2 })
2121
const parts = nf.formatToParts(value)
2222

2323
const [wholeParts, decimalParts] = splitOnceBy(parts, (p) => p.type === 'decimal')
@@ -58,9 +58,7 @@ export function round(num: number, digits: number) {
5858
return Number(nf.format(num))
5959
}
6060

61-
// a separate function because I wanted to test it with a bunch of locales
62-
// to make sure the toLowerCase thing is ok
63-
export const toEngNotation = (num: number | bigint, locale = navigator.language) =>
61+
const toEngNotation = (num: number | bigint, locale?: string) =>
6462
Intl.NumberFormat(locale, { notation: 'engineering', maximumFractionDigits: 1 })
6563
.format(num)
6664
.toLowerCase()
@@ -72,8 +70,12 @@ export const toEngNotation = (num: number | bigint, locale = navigator.language)
7270
*
7371
* Boolean represents whether the number was abbreviated.
7472
*/
75-
export function displayBigNum(num: bigint | number): [string, boolean] {
76-
const compact = Intl.NumberFormat(navigator.language, {
73+
export function displayBigNum(
74+
num: bigint | number,
75+
/** Argument here for testing purposes. Leave undefined in app code! */
76+
locale?: string
77+
): [string, boolean] {
78+
const compact = Intl.NumberFormat(locale, {
7779
notation: 'compact',
7880
maximumFractionDigits: 1,
7981
})
@@ -83,8 +85,8 @@ export function displayBigNum(num: bigint | number): [string, boolean] {
8385
const result = abbreviated
8486
? num < 1e15 // this the threshold where compact stops using nice letters. see tests
8587
? compact.format(num)
86-
: toEngNotation(num)
87-
: num.toLocaleString()
88+
: toEngNotation(num, locale)
89+
: num.toLocaleString(locale)
8890

8991
return [result, abbreviated]
9092
}

test/e2e/ip-pools.e2e.ts

+18
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ test('IP pool list', async ({ page }) => {
3333
})
3434
})
3535

36+
test.describe('german locale', () => {
37+
test.use({ locale: 'de-DE' })
38+
39+
test('IP pools list renders bignum with correct locale', async ({ page }) => {
40+
await page.goto('/system/networking/ip-pools')
41+
const table = page.getByRole('table')
42+
await expectRowVisible(table, {
43+
name: 'ip-pool-4',
44+
Utilization: 'v4' + '0 / 207' + 'v6' + '0 / 18,4e18',
45+
})
46+
})
47+
48+
test('IP pool CapacityBar renders bignum with correct locale', async ({ page }) => {
49+
await page.goto('/system/networking/ip-pools/ip-pool-4')
50+
await expect(page.getByText('Capacity18,4e18')).toBeVisible()
51+
})
52+
})
53+
3654
test('IP pool silo list', async ({ page }) => {
3755
await page.goto('/system/networking/ip-pools')
3856

0 commit comments

Comments
 (0)