Fix 1000k counts and decimal digits of integers in number utilities
What does this MR do and why?
This fixes two small bugs in app/assets/javascripts/lib/utils/number_utils.js, each with the spec rows that reproduce it.
numberToMetricPrefix picked the k unit with number < MILLION and rounded afterwards, so 999950 to 999999 rounded to 1000.0 thousands and rendered as 1000k (or 1000K) instead of 1m, which is what 1000000c gives. It now rounds the value in thousands first and keeps the k unit only while the rounded value is below 1000. The function formats counts in the super sidebar, the groups and projects lists, the issuable tabs and the group and project delete modals, so a count in that range now shows 1m. GLQL's compact count formatter already rounds 999999 up the same way, to 1M (its spec row).
countFloatingPointDigits returned 4 for every non-zero integer (5, 12, '7'). splitDecimalNumber returns decimal: null when the value has no decimal part, and the function measured String(decimal).length, which is the length of the string "null". It now returns the length of the decimal part when there is one and 0 otherwise. Its only caller, metric_tile.vue, calls it only for non-integer values, which have a decimal part unless written in exponent notation (1e-7), so in practice nothing renders differently there; the fix keeps the exported utility correct for other callers.
Behaviour change: numberToMetricPrefix renders values from 999950 to 999999 as 1m instead of 1000k, and every other value as before. Values from 999950000 up still render in millions (1000m, 1500m and so on), because the function has no unit above m; I left that alone.
References
No issue tracks these two bugs. The spec rows and the screenshots below show them on master.
Screenshots or screen recordings
Explore > Projects on GitLab CE 19.5.0 (the official Docker image), signed out, with the star counts of three projects set in the database to 1000000c, 999950 and 999949. The After image is the same page with the served bundle's numberToMetricPrefix changed in the browser the way this MR changes the source; it is not a build of this branch.
| Before | After |
|---|---|
![]() |
![]() |
How to set up and validate locally
- Run
yarn jest spec/frontend/lib/utils/number_utils_spec.js. All 93 examples pass. - Run
git checkout master -- app/assets/javascripts/lib/utils/number_utils.jsand run the spec again. Five of the new rows fail:countFloatingPointDigitsreturns 4 for5,12and'7', andnumberToMetricPrefixreturns1000kfor 999950 and 999999. - Run
git checkout HEAD -- app/assets/javascripts/lib/utils/number_utils.jsto restore the fix.
What I ran
On master at f0464c04, with Node 22.23.1 and the frozen yarn.lock:
spec/frontend/lib/utils/number_utils_spec.jswithmaster'snumber_utils.js: 5 failed and 88 passed, each failure on the defect itself (Received: 4andReceived: "1000k"). With the fix: 93 passed.- That spec and the specs of every caller of the two functions, CE and EE, with the frontend fixtures the package registry holds for a
mastercommit two commits earlier: 21 suites and 563 examples pass. They includetabs_with_list_spec.js,groups_list_item_spec.js,projects_list_item_spec.jsandorganization_group_stats_spec.js, which load generated fixtures, andsuper_sidebar/utils_spec.js,sidebar_menu_spec.js, both delete modal specs,issuable_tabs_spec.js,metric_tile_spec.js,delete_modal_secrets_count_spec.jsand the observability usage specs. - Three mutants of the fix (an integer fallback of 1,
<=instead of<against 1000, and the old unrounded condition) each fail the new rows. yarn run lint:eslintand Prettier on the two changed files are clean, andscripts/lint/commit_linter.rbaccepts the commit message.
The new rows without the fix, condensed from the Jest output:
passed returns 999.9k given 999949
failed returns 1m given 999950 Expected: "1m" Received: "1000k"
failed returns 1m given 999999 Expected: "1m" Received: "1000k"
failed when called with 5 it returns 0 Expected: 0 Received: 4
failed when called with 12 it returns 0 Expected: 0 Received: 4
failed when called with 7 it returns 0 Expected: 0 Received: 4
Tests: 5 failed, 88 passed, 93 totalWith the fix:
Tests: 93 passed, 93 totalI found these while maintaining gitlab-mcp-server; its upstream-bugs.md records everything done on its dependencies and sibling projects.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

