177 lines
6.4 KiB
TypeScript
177 lines
6.4 KiB
TypeScript
/**
|
|
* 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);
|
|
});
|
|
});
|
|
});
|