UNPKG

rampensau

Version:

Color ramp generator using curves within the HSL color model

131 lines (114 loc) 4.84 kB
import { describe, it, expect } from 'vitest'; import { shuffleArray, scaleSpreadArray, makeCurveEasings, pointOnCurve } from '../src/utils'; // Define lerp function locally for testing const lerp = (amt: number, from: number, to: number): number => from + amt * (to - from); describe('shuffleArray', () => { it('should return an array with the same length', () => { const original = [1, 2, 3, 4, 5]; const shuffled = shuffleArray(original); expect(shuffled).toHaveLength(original.length); }); it('should contain the same elements', () => { const original = [1, 2, 3, 4, 5]; const shuffled = shuffleArray(original); expect(shuffled).toEqual(expect.arrayContaining(original)); expect(original).toEqual(expect.arrayContaining(shuffled)); }); it('should shuffle the array (usually)', () => { const original = Array.from({ length: 100 }, (_, i) => i); const shuffled = shuffleArray(original); // It's statistically improbable but possible for the array to remain unchanged expect(shuffled).not.toEqual(original); }); it('should use the provided random function', () => { const original = [1, 2, 3]; // A deterministic "random" function that cycles through 0.5, 0.2, 0.8 const mockRndFn = (() => { const sequence = [0.5, 0.2, 0.8]; let index = 0; return () => sequence[index++ % sequence.length]; })(); const shuffled = shuffleArray(original, mockRndFn); // With this mock, the shuffle should produce a predictable result expect(shuffled).toEqual([3, 1, 2]); }); }); describe('lerp', () => { it('should interpolate correctly', () => { expect(lerp(0, 0, 10)).toBe(0); expect(lerp(1, 0, 10)).toBe(10); expect(lerp(0.5, 0, 10)).toBe(5); expect(lerp(0.25, 10, 20)).toBe(12.5); expect(lerp(0.75, -10, 10)).toBe(5); }); }); describe('scaleSpreadArray', () => { it('should scale and spread the array correctly with lerp', () => { const initial = [0, 10]; const targetSize = 5; const expected = [0, 2.5, 5, 7.5, 10]; const result = scaleSpreadArray(initial, targetSize, 0, lerp); expect(result).toHaveLength(targetSize); result.forEach((val, i) => expect(val).toBeCloseTo(expected[i] as number)); }); it('should handle arrays with more than two elements', () => { const initial = [0, 10, 5]; const targetSize = 7; // Expected: [0, 5, 10, 7.5, 5, ?, ?] - Calculation gets complex, focus on length and bounds const result = scaleSpreadArray(initial, targetSize, 0, lerp); expect(result).toHaveLength(targetSize); expect(result[0]).toBe(0); expect(result[2]).toBe(6.666666666666666); // Second original element position expect(result[4]).toBe(8.333333333333334); // Third original element position }); it('should throw error if initial array is too small', () => { expect(() => scaleSpreadArray([1], 8.333333333333334)).toThrow(); }); it('should throw error if target size is smaller than initial size', () => { expect(() => scaleSpreadArray([1, 2, 3], 2)).toThrow(); }); }); describe('pointOnCurve', () => { it('should return points for "lamé" curve', () => { const poc = pointOnCurve('lamé', 0.5); const point = poc(0.5); expect(point.x).toBeGreaterThanOrEqual(0); expect(point.x).toBeLessThanOrEqual(1); expect(point.y).toBeGreaterThanOrEqual(0); expect(point.y).toBeLessThanOrEqual(1); }); it('should return points for "arc" curve', () => { const poc = pointOnCurve('arc', 0.1); const point = poc(0.2); expect(point.x).toBeGreaterThanOrEqual(0); expect(point.x).toBeLessThanOrEqual(1); expect(point.y).toBeGreaterThanOrEqual(0); expect(point.y).toBeLessThanOrEqual(1); }); /* it('should throw error for invalid curve method', () => { // @ts-expect-error Testing invalid input expect(() => pointOnCurve('invalidMethod', 0.5)).toThrow( 'pointOnCurve() curveAccent parameter is expected to be "lamé" | "arc" | "pow" | "powY" | "powX" or a function but `invalidMethod` given.' ); });*/ }); describe('makeCurveEasings', () => { it('should return sEasing and lEasing functions', () => { const easings = makeCurveEasings('lamé', 0.5); expect(easings.sEasing).toBeInstanceOf(Function); expect(easings.lEasing).toBeInstanceOf(Function); }); it('easing functions should return values between 0 and 1 for t between 0 and 1', () => { const easings = makeCurveEasings('lamé', 0.5); const tValues = [0, 0.25, 0.5, 0.75, 1]; tValues.forEach(t => { const sVal = easings.sEasing(t); const lVal = easings.lEasing(t); expect(sVal).toBeGreaterThanOrEqual(0); expect(sVal).toBeLessThanOrEqual(1); expect(lVal).toBeGreaterThanOrEqual(0); expect(lVal).toBeLessThanOrEqual(1); }); }); });