'use strict'; const { normalizeValue, toMetricName } = require('../src/normalize'); describe('normalizeValue', () => { test('type 6 (pH): raw / 100', () => { expect(normalizeValue(735, 6)).toBeCloseTo(7.35); }); test('type 133 (water temp): raw / 100', () => { expect(normalizeValue(2450, 133)).toBeCloseTo(24.5); }); test('type 8 (pressure): (1.5 * raw - 500) / 1000', () => { // raw = 800 → (1.5 * 800 - 500) / 1000 = (1200 - 500) / 1000 = 0.7 expect(normalizeValue(800, 8)).toBeCloseTo(0.7); }); test('type 5 (temperature): passthrough', () => { expect(normalizeValue(22, 5)).toBe(22); }); test('type 12 (moisture): passthrough', () => { expect(normalizeValue(54, 12)).toBe(54); }); test('type 2 (binary): passthrough', () => { expect(normalizeValue(1, 2)).toBe(1); expect(normalizeValue(0, 2)).toBe(0); }); test('null raw value returns null', () => { expect(normalizeValue(null, 6)).toBeNull(); expect(normalizeValue(undefined, 12)).toBeNull(); }); test('unknown type code: passthrough', () => { expect(normalizeValue(42, 999)).toBe(42); }); }); describe('normalizeValue with apiExpression', () => { test('apiExpression overrides hardcoded type expression', () => { // type 133 hardcoded: v/100 — override with v/10 expect(normalizeValue(190, 133, 'value/10')).toBeCloseTo(19.0); }); test('apiExpression used when typeDef has no expression', () => { expect(normalizeValue(250, 5, 'value/10')).toBeCloseTo(25.0); }); test('unsafe expression rejected, falls back to type default', () => { // type 133 hardcoded: v/100 expect(normalizeValue(2450, 133, 'require("fs")')).toBeCloseTo(24.5); }); test('null apiExpression falls back to type expression', () => { expect(normalizeValue(735, 6, null)).toBeCloseTo(7.35); }); test('complex expression (pressure)', () => { expect(normalizeValue(800, 8, '(1.5*value-500)/1000')).toBeCloseTo(0.7); }); }); describe('toMetricName', () => { test('lowercases and replaces spaces', () => { expect(toMetricName('Plumbago Humidity', 0)).toBe('plumbago_humidity'); }); test('strips non-alphanumeric except underscore', () => { expect(toMetricName('pH (pool)', 0)).toBe('ph_pool'); }); test('falls back to input_{index} when name empty', () => { expect(toMetricName('', 3)).toBe('input_3'); expect(toMetricName(null, 1)).toBe('input_1'); }); test('handles already clean names', () => { expect(toMetricName('temperature', 0)).toBe('temperature'); }); });