/** * Tests for clampNumber utility */ import { describe, expect, test, } from 'vitest'; import { clampNumber } from './clampNumber'; describe('clampNumber', () => { describe('basic functionality', () => { test('should return value when within range', () => { expect(clampNumber(5, 0, 10)).toBe(5); expect(clampNumber(0.5, 0, 1)).toBe(0.5); expect(clampNumber(-3, -10, 10)).toBe(-3); }); test('should clamp value to minimum', () => { expect(clampNumber(-5, 0, 10)).toBe(0); expect(clampNumber(-100, -50, 100)).toBe(-50); expect(clampNumber(0, 1, 10)).toBe(1); }); test('should clamp value to maximum', () => { expect(clampNumber(15, 0, 10)).toBe(10); expect(clampNumber(150, -50, 100)).toBe(100); expect(clampNumber(100, 1, 50)).toBe(50); }); test('should handle boundary values', () => { expect(clampNumber(0, 0, 10)).toBe(0); expect(clampNumber(10, 0, 10)).toBe(10); expect(clampNumber(-5, -5, 5)).toBe(-5); expect(clampNumber(5, -5, 5)).toBe(5); }); }); describe('negative ranges', () => { test('should handle fully negative ranges', () => { expect(clampNumber(-5, -10, -1)).toBe(-5); expect(clampNumber(-15, -10, -1)).toBe(-10); expect(clampNumber(-0.5, -10, -1)).toBe(-1); }); test('should handle ranges spanning zero', () => { expect(clampNumber(0, -10, 10)).toBe(0); expect(clampNumber(-5, -10, 10)).toBe(-5); expect(clampNumber(5, -10, 10)).toBe(5); }); }); describe('floating-point numbers', () => { test('should clamp floating-point values correctly', () => { expect(clampNumber(0.75, 0, 1)).toBe(0.75); expect(clampNumber(1.5, 0, 1)).toBe(1); expect(clampNumber(-0.25, 0, 1)).toBe(0); }); test('should handle very small decimals', () => { expect(clampNumber(0.001, 0, 0.01)).toBe(0.001); expect(clampNumber(0.1, 0, 0.01)).toBe(0.01); }); test('should handle large floating-point numbers', () => { expect(clampNumber(123.456, 100, 200)).toBe(123.456); expect(clampNumber(99.999, 100, 200)).toBe(100); expect(clampNumber(200.001, 100, 200)).toBe(200); }); }); describe('edge cases', () => { test('should handle when min equals max', () => { expect(clampNumber(5, 10, 10)).toBe(10); expect(clampNumber(10, 10, 10)).toBe(10); expect(clampNumber(15, 10, 10)).toBe(10); expect(clampNumber(0, 0, 0)).toBe(0); }); test('should handle zero values', () => { expect(clampNumber(0, 0, 10)).toBe(0); expect(clampNumber(0, -10, 10)).toBe(0); expect(clampNumber(5, 0, 0)).toBe(0); }); test('should handle reversed min/max (min > max)', () => { // When min > max, Math.max/Math.min will still produce a result // but it's logically incorrect - we test the actual behavior // Math.min(Math.max(5, 10), 0) = Math.min(10, 0) = 0 expect(clampNumber(5, 10, 0)).toBe(0); expect(clampNumber(15, 10, 0)).toBe(0); expect(clampNumber(-5, 10, 0)).toBe(0); }); }); describe('special number values', () => { test('should handle Infinity', () => { expect(clampNumber(Infinity, 0, 10)).toBe(10); expect(clampNumber(-Infinity, 0, 10)).toBe(0); expect(clampNumber(5, -Infinity, Infinity)).toBe(5); }); test('should handle NaN', () => { expect(clampNumber(NaN, 0, 10)).toBeNaN(); }); }); describe('real-world scenarios', () => { test('should clamp font size values', () => { // Typical font size range: 8px to 72px expect(clampNumber(16, 8, 72)).toBe(16); expect(clampNumber(4, 8, 72)).toBe(8); expect(clampNumber(100, 8, 72)).toBe(72); }); test('should clamp slider values', () => { // Slider range: 0 to 100 expect(clampNumber(50, 0, 100)).toBe(50); expect(clampNumber(-10, 0, 100)).toBe(0); expect(clampNumber(150, 0, 100)).toBe(100); }); test('should clamp opacity values', () => { // Opacity range: 0 to 1 expect(clampNumber(0.5, 0, 1)).toBe(0.5); expect(clampNumber(-0.2, 0, 1)).toBe(0); expect(clampNumber(1.2, 0, 1)).toBe(1); }); test('should clamp percentage values', () => { // Percentage range: 0 to 100 expect(clampNumber(75, 0, 100)).toBe(75); expect(clampNumber(-5, 0, 100)).toBe(0); expect(clampNumber(105, 0, 100)).toBe(100); }); test('should clamp coordinate values', () => { // Canvas coordinates: 0 to 800 width, 0 to 600 height expect(clampNumber(400, 0, 800)).toBe(400); expect(clampNumber(-50, 0, 800)).toBe(0); expect(clampNumber(900, 0, 800)).toBe(800); }); test('should clamp font weight values', () => { // Font weight range: 100 to 900 (in increments of 100) expect(clampNumber(400, 100, 900)).toBe(400); expect(clampNumber(50, 100, 900)).toBe(100); expect(clampNumber(950, 100, 900)).toBe(900); }); test('should clamp line height values', () => { // Line height range: 0.5 to 3.0 expect(clampNumber(1.5, 0.5, 3.0)).toBe(1.5); expect(clampNumber(0.3, 0.5, 3.0)).toBe(0.5); expect(clampNumber(4.0, 0.5, 3.0)).toBe(3.0); }); }); describe('numeric constraints', () => { test('should handle very large numbers', () => { expect(clampNumber(Number.MAX_VALUE, 0, 100)).toBe(100); expect(clampNumber(Number.MIN_VALUE, -10, 10)).toBe(Number.MIN_VALUE); }); test('should handle negative infinity boundaries', () => { expect(clampNumber(5, -Infinity, 10)).toBe(5); expect(clampNumber(-1000, -Infinity, 10)).toBe(-1000); }); test('should handle positive infinity boundaries', () => { expect(clampNumber(5, 0, Infinity)).toBe(5); expect(clampNumber(1000, 0, Infinity)).toBe(1000); }); }); });