fix(integrations): round imported provider values through one normaliser

Fitbit, WHOOP, Oura, Polar and Withings each kept a private
`parseFloat(n.toFixed(2))`, which mis-rounds halves on the double below
the decimal. `importValue` keeps the same two places, rounds half away
from zero on the printed decimal and returns the nearest double, so a
value prints cleanly. A guard keeps `toFixed` and private `round2`
helpers out of the provider directories; the Google Health mapper is the
one listed exception until its next change.
This commit is contained in:
Marc-André Bombeck committed 2026-10-20 03:35:41 +02:00
1 parent e452dd62e2
commit 2b61762962
8 files changed
+188 -60

No files matched your search

@@ -0,0 +1,29 @@
import { describe, expect, it } from "vitest";
import { importValue } from "../import-value";
describe("importValue", () => {
it("drops the binary noise provider arithmetic leaves behind", () => {
expect(importValue(72.30000000000001)).toBe(72.3);
expect(importValue(0.1 + 0.2)).toBe(0.3);
// Withings: value * 10^unit.
expect(importValue(78456 * Math.pow(10, -3))).toBe(78.46);
expect(String(importValue(1234 * 0.01))).toBe("12.34");
});
it("rounds halves on the decimal the value prints as, away from zero", () => {
// `(1.005).toFixed(2)` is "1.00".
expect(importValue(1.005)).toBe(1.01);
expect(importValue(-0.125)).toBe(-0.13);
expect(importValue(2.675)).toBe(2.68);
});
it("keeps whole numbers, zero and non-finite values as they are", () => {
expect(importValue(64)).toBe(64);
expect(Object.is(importValue(-0.001), 0)).toBe(true);
expect(importValue(0)).toBe(0);
expect(importValue(Number.NaN)).toBeNaN();
expect(importValue(1e-7)).toBe(0);
expect(importValue(1e22)).toBe(1e22);
});
});