67 lines
2.0 KiB
TypeScript
67 lines
2.0 KiB
TypeScript
|
|
import { describe, it, expect } from 'vitest';
|
||
|
|
|
||
|
|
import { formatBerthRange } from '@/lib/templates/berth-range';
|
||
|
|
|
||
|
|
describe('formatBerthRange', () => {
|
||
|
|
it('returns "" for an empty list', () => {
|
||
|
|
expect(formatBerthRange([])).toBe('');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('returns a single mooring as-is, never "A5-A5"', () => {
|
||
|
|
expect(formatBerthRange(['A5'])).toBe('A5');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('compresses a consecutive run', () => {
|
||
|
|
expect(formatBerthRange(['A1', 'A2', 'A3'])).toBe('A1-A3');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('joins non-consecutive single moorings with comma', () => {
|
||
|
|
expect(formatBerthRange(['A1', 'A3'])).toBe('A1, A3');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('handles multiple runs across prefixes', () => {
|
||
|
|
expect(formatBerthRange(['A1', 'A2', 'B5', 'B6', 'B7'])).toBe('A1-A2, B5-B7');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('sorts unsorted input by (prefix, number)', () => {
|
||
|
|
expect(formatBerthRange(['B5', 'A1', 'A2'])).toBe('A1-A2, B5');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('dedupes', () => {
|
||
|
|
expect(formatBerthRange(['A1', 'A1', 'A2'])).toBe('A1-A2');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not run across prefixes (B1 after A11 stays separate)', () => {
|
||
|
|
expect(formatBerthRange(['A11', 'B1'])).toBe('A11, B1');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('mixed runs + singletons', () => {
|
||
|
|
expect(formatBerthRange(['A1', 'A2', 'A4', 'B5', 'B6'])).toBe('A1-A2, A4, B5-B6');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('handles multi-letter prefixes', () => {
|
||
|
|
expect(formatBerthRange(['AA1', 'AA2', 'BB7'])).toBe('AA1-AA2, BB7');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('treats numerically-sequential moorings as consecutive (A9 + A10)', () => {
|
||
|
|
expect(formatBerthRange(['A9', 'A10', 'A11'])).toBe('A9-A11');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('passes non-canonical inputs through unchanged', () => {
|
||
|
|
expect(formatBerthRange(['A1', 'A2', 'B-LEG'])).toBe('A1-A2, B-LEG');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('trims whitespace', () => {
|
||
|
|
expect(formatBerthRange([' A1 ', 'A2'])).toBe('A1-A2');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('drops empty strings without error', () => {
|
||
|
|
expect(formatBerthRange(['A1', '', 'A2'])).toBe('A1-A2');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('handles long ranges (50 consecutive)', () => {
|
||
|
|
const moorings = Array.from({ length: 50 }, (_, i) => `A${i + 1}`);
|
||
|
|
expect(formatBerthRange(moorings)).toBe('A1-A50');
|
||
|
|
});
|
||
|
|
});
|