import { describe, it, expect } from 'vitest' import { getCellValue, compareValues, sortData, paginateData } from './helpers' describe('helpers', () => { describe('getCellValue', () => { it('should return empty string for null', () => { expect(getCellValue(null)).toBe('') }) it('should return empty string for undefined', () => { expect(getCellValue(undefined)).toBe('') }) it('should return string as-is', () => { expect(getCellValue('hello')).toBe('hello') }) it('should return number as-is', () => { expect(getCellValue(42)).toBe(42) }) it('should return boolean as-is', () => { expect(getCellValue(true)).toBe(true) expect(getCellValue(false)).toBe(false) }) it('should format array of strings with quotes', () => { expect(getCellValue(['a', 'b', 'c'])).toBe('["a", "b", "c"]') }) it('should format array of numbers without quotes', () => { expect(getCellValue([1, 2, 3])).toBe('[1, 2, 3]') }) it('should format mixed array', () => { expect(getCellValue(['hello', 42, true])).toBe('["hello", 42, true]') }) it('should format empty array', () => { expect(getCellValue([])).toBe('[]') }) it('should stringify object', () => { expect(getCellValue({ key: 'value' })).toBe('{"key":"value"}') }) it('should stringify nested object', () => { expect(getCellValue({ a: { b: 'c' } })).toBe('{"a":{"b":"c"}}') }) }) describe('compareValues', () => { describe('null/undefined handling', () => { it('should sort null to end (return 1)', () => { expect(compareValues(null, 'a', 'asc')).toBe(1) }) it('should sort undefined to end (return 1)', () => { expect(compareValues(undefined, 'a', 'asc')).toBe(1) }) it('should sort non-null before null (return -1)', () => { expect(compareValues('a', null, 'asc')).toBe(-1) }) it('should sort non-undefined before undefined (return -1)', () => { expect(compareValues('a', undefined, 'asc')).toBe(-1) }) }) describe('string comparison', () => { it('should compare strings ascending', () => { expect(compareValues('apple', 'banana', 'asc')).toBeLessThan(0) expect(compareValues('banana', 'apple', 'asc')).toBeGreaterThan(0) expect(compareValues('apple', 'apple', 'asc')).toBe(0) }) it('should compare strings descending', () => { expect(compareValues('apple', 'banana', 'desc')).toBeGreaterThan(0) expect(compareValues('banana', 'apple', 'desc')).toBeLessThan(0) // When values are equal, result is 0 (could be -0 or +0, both equal 0) expect(compareValues('apple', 'apple', 'desc') === 0).toBe(true) }) }) describe('number comparison', () => { it('should compare numbers ascending', () => { expect(compareValues(1, 2, 'asc')).toBeLessThan(0) expect(compareValues(2, 1, 'asc')).toBeGreaterThan(0) expect(compareValues(1, 1, 'asc')).toBe(0) }) it('should compare numbers descending', () => { expect(compareValues(1, 2, 'desc')).toBeGreaterThan(0) expect(compareValues(2, 1, 'desc')).toBeLessThan(0) // When values are equal, result is 0 (could be -0 or +0, both equal 0) expect(compareValues(1, 1, 'desc') === 0).toBe(true) }) it('should handle negative numbers', () => { expect(compareValues(-5, 5, 'asc')).toBeLessThan(0) expect(compareValues(5, -5, 'asc')).toBeGreaterThan(0) }) it('should handle decimal numbers', () => { expect(compareValues(1.5, 2.5, 'asc')).toBeLessThan(0) expect(compareValues(2.5, 1.5, 'asc')).toBeGreaterThan(0) }) }) describe('boolean comparison', () => { it('should compare booleans ascending (false before true)', () => { expect(compareValues(false, true, 'asc')).toBeLessThan(0) expect(compareValues(true, false, 'asc')).toBeGreaterThan(0) expect(compareValues(true, true, 'asc')).toBe(0) expect(compareValues(false, false, 'asc')).toBe(0) }) it('should compare booleans descending (true before false)', () => { expect(compareValues(false, true, 'desc')).toBeGreaterThan(0) expect(compareValues(true, false, 'desc')).toBeLessThan(0) }) }) describe('object comparison', () => { it('should compare objects as JSON strings', () => { const objA = { a: 1 } const objB = { b: 2 } // Compares '{"a":1}' vs '{"b":2}' expect(compareValues(objA, objB, 'asc')).toBeLessThan(0) }) it('should handle array comparison', () => { const arrA = [1, 2] const arrB = [3, 4] // Compares '[1,2]' vs '[3,4]' expect(compareValues(arrA, arrB, 'asc')).toBeLessThan(0) }) }) }) describe('sortData', () => { const testData = [ { id: 1, name: 'Charlie', age: 30 }, { id: 2, name: 'Alice', age: 25 }, { id: 3, name: 'Bob', age: 35 }, ] it('should sort by string column ascending', () => { const sorted = sortData(testData, 'name', 'asc') expect(sorted.map((r) => r.name)).toEqual(['Alice', 'Bob', 'Charlie']) }) it('should sort by string column descending', () => { const sorted = sortData(testData, 'name', 'desc') expect(sorted.map((r) => r.name)).toEqual(['Charlie', 'Bob', 'Alice']) }) it('should sort by number column ascending', () => { const sorted = sortData(testData, 'age', 'asc') expect(sorted.map((r) => r.age)).toEqual([25, 30, 35]) }) it('should sort by number column descending', () => { const sorted = sortData(testData, 'age', 'desc') expect(sorted.map((r) => r.age)).toEqual([35, 30, 25]) }) it('should not mutate original array', () => { const original = [...testData] sortData(testData, 'name', 'asc') expect(testData).toEqual(original) }) it('should handle empty array', () => { expect(sortData([], 'name', 'asc')).toEqual([]) }) it('should handle single item array', () => { const single = [{ id: 1, name: 'Alice' }] expect(sortData(single, 'name', 'asc')).toEqual(single) }) it('should handle null values in data', () => { const dataWithNull = [ { id: 1, name: 'Bob' }, { id: 2, name: null }, { id: 3, name: 'Alice' }, ] const sorted = sortData(dataWithNull, 'name', 'asc') // Null should be sorted to end expect(sorted.map((r) => r.name)).toEqual(['Alice', 'Bob', null]) }) }) describe('paginateData', () => { const testData = [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }, { id: 8 }, { id: 9 }, { id: 10 }, ] it('should return first page', () => { const result = paginateData(testData, 0, 3) expect(result.map((r) => r.id)).toEqual([1, 2, 3]) }) it('should return second page', () => { const result = paginateData(testData, 1, 3) expect(result.map((r) => r.id)).toEqual([4, 5, 6]) }) it('should return partial last page', () => { const result = paginateData(testData, 3, 3) expect(result.map((r) => r.id)).toEqual([10]) }) it('should return empty array for page beyond data', () => { const result = paginateData(testData, 10, 3) expect(result).toEqual([]) }) it('should handle page size larger than data', () => { const result = paginateData(testData, 0, 100) expect(result.map((r) => r.id)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) }) it('should handle empty array', () => { expect(paginateData([], 0, 10)).toEqual([]) }) it('should handle single item', () => { const result = paginateData([{ id: 1 }], 0, 10) expect(result.map((r) => r.id)).toEqual([1]) }) }) })