Files
connectai/tests/sheetsApi.test.ts
T

114 lines
3.8 KiB
TypeScript

import {
parseTsvBody,
valuesToMarkdownTable,
} from '../src/features/sheets/sheetsApi';
import { _parseSheetAttrs } from '../src/agent';
describe('parseTsvBody', () => {
test('returns [] for empty / whitespace input', () => {
expect(parseTsvBody('')).toEqual([]);
expect(parseTsvBody(' ')).toEqual([]);
expect(parseTsvBody('\n\n')).toEqual([]);
});
test('parses tab-separated rows', () => {
const body = '이름\t나이\t직책\n민지\t29\t디자이너\n준호\t31\t개발자';
expect(parseTsvBody(body)).toEqual([
['이름', '나이', '직책'],
['민지', '29', '디자이너'],
['준호', '31', '개발자'],
]);
});
test('falls back to pipe-separated when no tab present', () => {
const body = '이름 | 나이\n민지 | 29\n준호 | 31';
expect(parseTsvBody(body)).toEqual([
['이름', '나이'],
['민지', '29'],
['준호', '31'],
]);
});
test('strips leading and trailing blank lines (LLM artifact)', () => {
const body = '\n\n이름\t나이\n민지\t29\n\n';
expect(parseTsvBody(body)).toEqual([
['이름', '나이'],
['민지', '29'],
]);
});
test('preserves empty cells when tabs are present', () => {
const body = 'A\t\tC';
expect(parseTsvBody(body)).toEqual([['A', '', 'C']]);
});
});
describe('valuesToMarkdownTable', () => {
test('empty → placeholder', () => {
expect(valuesToMarkdownTable([])).toBe('_(empty)_');
});
test('renders header + separator + rows', () => {
const out = valuesToMarkdownTable([
['이름', '나이'],
['민지', 29],
['준호', 31],
]);
const lines = out.split('\n');
expect(lines[0]).toBe('| 이름 | 나이 |');
expect(lines[1]).toBe('|---|---|');
expect(lines[2]).toBe('| 민지 | 29 |');
expect(lines[3]).toBe('| 준호 | 31 |');
});
test('truncates beyond maxRows + adds note', () => {
const big: any[][] = [['col']];
for (let i = 0; i < 60; i++) big.push([`row${i}`]);
const out = valuesToMarkdownTable(big, 10);
expect(out).toContain('| col |');
expect(out).toContain('| row0 |');
expect(out).toContain('| row8 |'); // 10 rows total = header + 9 data
expect(out).not.toContain('| row9 |');
expect(out).toContain('51 more rows truncated');
});
test('escapes pipe characters inside cell values', () => {
const out = valuesToMarkdownTable([
['a|b', 'c'],
['d', 'e|f'],
]);
expect(out).toContain('| a\\|b | c |');
expect(out).toContain('| d | e\\|f |');
});
});
describe('_parseSheetAttrs', () => {
test('parses spreadsheet_id + range with double quotes', () => {
const a = _parseSheetAttrs(' spreadsheet_id="1abc" range="Sheet1!A1:D20" ');
expect(a.spreadsheetId).toBe('1abc');
expect(a.range).toBe('Sheet1!A1:D20');
});
test('accepts camelCase alias spreadsheetId', () => {
const a = _parseSheetAttrs('spreadsheetId="1xyz" range="A:B"');
expect(a.spreadsheetId).toBe('1xyz');
});
test('accepts sheet_id alias', () => {
const a = _parseSheetAttrs(`sheet_id='1qrs' range='Tab1'`);
expect(a.spreadsheetId).toBe('1qrs');
expect(a.range).toBe('Tab1');
});
test('parses bare (unquoted) values', () => {
const a = _parseSheetAttrs('spreadsheet_id=1simple range=Sheet1!A1');
expect(a.spreadsheetId).toBe('1simple');
expect(a.range).toBe('Sheet1!A1');
});
test('returns empty for missing attrs', () => {
expect(_parseSheetAttrs('')).toEqual({});
expect(_parseSheetAttrs('foo="bar"')).toEqual({});
});
});