UNPKG

@borgar/fx

Version:

Utilities for working with Excel formulas

234 lines (198 loc) 7.45 kB
/* eslint-disable @stylistic/object-property-newline */ import { describe, test, expect } from 'vitest'; import { fromRow, parseA1Range } from './parseA1Range.ts'; describe('fromRow', () => { test('fromRow converts row strings to zero-based indices', () => { expect(fromRow('1')).toBe(0); expect(fromRow('2')).toBe(1); expect(fromRow('10')).toBe(9); expect(fromRow('100')).toBe(99); expect(fromRow('9999999')).toBe(9999998); }); }); describe('parseA1Range', () => { test('parseA1Range parses simple cell references', () => { expect(parseA1Range('A1')).toEqual({ top: 0, left: 0, bottom: 0, right: 0, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('B2')).toEqual({ top: 1, left: 1, bottom: 1, right: 1, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('Z10')).toEqual({ top: 9, left: 25, bottom: 9, right: 25, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('AA100')).toEqual({ top: 99, left: 26, bottom: 99, right: 26, $top: false, $left: false, $bottom: false, $right: false }); }); }); test('parseA1Range parses absolute cell references', () => { expect(parseA1Range('$A$1')).toEqual({ top: 0, left: 0, bottom: 0, right: 0, $top: true, $left: true, $bottom: true, $right: true }); expect(parseA1Range('$A1')).toEqual({ top: 0, left: 0, bottom: 0, right: 0, $top: false, $left: true, $bottom: false, $right: true }); expect(parseA1Range('A$1')).toEqual({ top: 0, left: 0, bottom: 0, right: 0, $top: true, $left: false, $bottom: true, $right: false }); }); test('parseA1Range parses range references', () => { expect(parseA1Range('A1:B2')).toEqual({ top: 0, left: 0, bottom: 1, right: 1, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('A1:Z10')).toEqual({ top: 0, left: 0, bottom: 9, right: 25, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('B2:D4')).toEqual({ top: 1, left: 1, bottom: 3, right: 3, $top: false, $left: false, $bottom: false, $right: false }); }); test('parseA1Range parses range references with mixed absolute/relative', () => { expect(parseA1Range('$A$1:B2')).toEqual({ top: 0, left: 0, bottom: 1, right: 1, $top: true, $left: true, $bottom: false, $right: false }); expect(parseA1Range('A1:$B$2')).toEqual({ top: 0, left: 0, bottom: 1, right: 1, $top: false, $left: false, $bottom: true, $right: true }); expect(parseA1Range('$A1:B$2')).toEqual({ top: 0, left: 0, bottom: 1, right: 1, $top: false, $left: true, $bottom: true, $right: false }); }); test('parseA1Range normalizes reversed ranges', () => { expect(parseA1Range('B2:A1')).toEqual({ top: 0, left: 0, bottom: 1, right: 1, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('Z10:A1')).toEqual({ top: 0, left: 0, bottom: 9, right: 25, $top: false, $left: false, $bottom: false, $right: false }); }); test('parseA1Range parses column ranges', () => { expect(parseA1Range('A:A')).toEqual({ top: null, left: 0, bottom: null, right: 0, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('A:C')).toEqual({ top: null, left: 0, bottom: null, right: 2, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('C:A')).toEqual({ top: null, left: 0, bottom: null, right: 2, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('$A:C')).toEqual({ top: null, left: 0, bottom: null, right: 2, $top: false, $left: true, $bottom: false, $right: false }); expect(parseA1Range('A:$C')).toEqual({ top: null, left: 0, bottom: null, right: 2, $top: false, $left: false, $bottom: false, $right: true }); }); test('parseA1Range parses row ranges', () => { expect(parseA1Range('1:1')).toEqual({ top: 0, left: null, bottom: 0, right: null, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('1:3')).toEqual({ top: 0, left: null, bottom: 2, right: null, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('3:1')).toEqual({ top: 0, left: null, bottom: 2, right: null, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('$1:3')).toEqual({ top: 0, left: null, bottom: 2, right: null, $top: true, $left: false, $bottom: false, $right: false }); expect(parseA1Range('1:$3')).toEqual({ top: 0, left: null, bottom: 2, right: null, $top: false, $left: false, $bottom: true, $right: false }); }); test('parseA1Range parses trimmed ranges', () => { expect(parseA1Range('A1.:B2')).toEqual({ top: 0, left: 0, bottom: 1, right: 1, $top: false, $left: false, $bottom: false, $right: false, trim: 'head' }); expect(parseA1Range('A1:.B2')).toEqual({ top: 0, left: 0, bottom: 1, right: 1, $top: false, $left: false, $bottom: false, $right: false, trim: 'tail' }); expect(parseA1Range('A1.:.B2')).toEqual({ top: 0, left: 0, bottom: 1, right: 1, $top: false, $left: false, $bottom: false, $right: false, trim: 'both' }); }); test('parseA1Range handles partial column ranges', () => { const range = { top: 0, left: 0, bottom: null, right: 2, $top: false, $left: false, $bottom: false, $right: false }; expect(parseA1Range('A1:C')).toEqual(range); expect(parseA1Range('C:A1')).toEqual(range); }); test('parseA1Range handles partial row ranges', () => { const range = { top: 0, left: 0, bottom: 2, right: null, $top: false, $left: false, $bottom: false, $right: false }; expect(parseA1Range('A1:3')).toEqual(range); expect(parseA1Range('3:A1')).toEqual(range); }); test('parseA1Range returns null for invalid references', () => { expect(parseA1Range('')).toBe(undefined); expect(parseA1Range('A')).toBe(undefined); expect(parseA1Range('1')).toBe(undefined); expect(parseA1Range('$A')).toBe(undefined); expect(parseA1Range('$1')).toBe(undefined); expect(parseA1Range('AAAA1')).toBe(undefined); expect(parseA1Range('A0')).toBe(undefined); expect(parseA1Range('A10000000')).toBe(undefined); expect(parseA1Range('123ABC')).toBe(undefined); expect(parseA1Range('A1:B2:C3')).toBe(undefined); expect(parseA1Range('A1::B2')).toBe(undefined); expect(parseA1Range('A1B2')).toBe(undefined); expect(parseA1Range('$$$A1')).toBe(undefined); }); test('parseA1Range handles maximum valid values', () => { expect(parseA1Range('XFD1048576')).toEqual({ top: 1048575, left: 16383, bottom: 1048575, right: 16383, $top: false, $left: false, $bottom: false, $right: false }); expect(parseA1Range('XFD1048577')).toBe(undefined); expect(parseA1Range('XFE1048576')).toBe(undefined); }); test('parseA1Range handles case insensitivity', () => { const lower = parseA1Range('a1'); const upper = parseA1Range('A1'); const mixed = parseA1Range('aA1'); expect(lower).toEqual(upper); expect(lower).toEqual({ top: 0, left: 0, bottom: 0, right: 0, $top: false, $left: false, $bottom: false, $right: false }); expect(mixed).toEqual({ top: 0, left: 26, bottom: 0, right: 26, $top: false, $left: false, $bottom: false, $right: false }); });