Files
EXCEL2JSON/src/lib/converter.spec.ts
2026-02-09 20:08:26 +08:00

146 lines
5.3 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { convertData, createDefaultMappings, applyTemplate, exportTemplate } from '$lib/converter.js';
import type { MappingConfig, RowData } from '$lib/types.js';
describe('createDefaultMappings', () => {
it('creates mappings from headers with correct defaults', () => {
const mappings = createDefaultMappings(['姓名', '年龄']);
expect(mappings).toHaveLength(2);
expect(mappings[0]).toEqual({
source: '姓名',
target: '姓名',
type: 'string',
format: undefined,
excludeIfEmpty: false,
defaultValue: '',
enabled: true
});
});
it('auto-detects date columns from row data', () => {
const rows: RowData[] = [
{ name: 'Alice', birthday: new Date('2000-01-01') },
{ name: 'Bob', birthday: new Date('1995-06-15') }
];
const mappings = createDefaultMappings(['name', 'birthday'], rows);
expect(mappings[0].type).toBe('string');
expect(mappings[1].type).toBe('date');
expect(mappings[1].format).toBe('YYYY-MM-DD');
});
});
describe('convertData', () => {
const rows: RowData[] = [
{ name: 'Alice', age: 30, active: 'true', notes: '' },
{ name: 'Bob', age: 25, active: 'false', notes: 'some note' }
];
it('converts with default string mappings', () => {
const mappings = createDefaultMappings(['name', 'age']);
const result = convertData(rows, mappings);
expect(result).toHaveLength(2);
expect(result[0]).toEqual({ name: 'Alice', age: '30' });
});
it('converts number type', () => {
const mappings: MappingConfig[] = [
{ source: 'age', target: 'age', type: 'number', excludeIfEmpty: false, defaultValue: '', enabled: true }
];
const result = convertData(rows, mappings);
expect(result[0]).toEqual({ age: 30 });
});
it('converts boolean type', () => {
const mappings: MappingConfig[] = [
{ source: 'active', target: 'isActive', type: 'boolean', excludeIfEmpty: false, defaultValue: '', enabled: true }
];
const result = convertData(rows, mappings);
expect(result[0]).toEqual({ isActive: true });
expect(result[1]).toEqual({ isActive: false });
});
it('excludes empty fields when excludeIfEmpty is true', () => {
const mappings: MappingConfig[] = [
{ source: 'notes', target: 'notes', type: 'string', excludeIfEmpty: true, defaultValue: '', enabled: true }
];
const result = convertData(rows, mappings);
expect(result[0]).toEqual({});
expect(result[1]).toEqual({ notes: 'some note' });
});
it('uses default value for empty fields', () => {
const mappings: MappingConfig[] = [
{ source: 'notes', target: 'notes', type: 'string', excludeIfEmpty: false, defaultValue: 'N/A', enabled: true }
];
const result = convertData(rows, mappings);
expect(result[0]).toEqual({ notes: 'N/A' });
});
it('returns null for empty fields with no default', () => {
const mappings: MappingConfig[] = [
{ source: 'notes', target: 'notes', type: 'string', excludeIfEmpty: false, defaultValue: '', enabled: true }
];
const result = convertData(rows, mappings);
expect(result[0]).toEqual({ notes: null });
});
it('skips disabled columns', () => {
const mappings: MappingConfig[] = [
{ source: 'name', target: 'name', type: 'string', excludeIfEmpty: false, defaultValue: '', enabled: false },
{ source: 'age', target: 'age', type: 'number', excludeIfEmpty: false, defaultValue: '', enabled: true }
];
const result = convertData(rows, mappings);
expect(result[0]).toEqual({ age: 30 });
});
it('renames target keys', () => {
const mappings: MappingConfig[] = [
{ source: 'name', target: 'full_name', type: 'string', excludeIfEmpty: false, defaultValue: '', enabled: true }
];
const result = convertData(rows, mappings);
expect(result[0]).toEqual({ full_name: 'Alice' });
});
});
describe('date conversion', () => {
it('formats Excel serial date numbers', () => {
const rows: RowData[] = [{ date: 44927 }]; // 2023-01-01
const mappings: MappingConfig[] = [
{ source: 'date', target: 'date', type: 'date', format: 'YYYY-MM-DD', excludeIfEmpty: false, defaultValue: '', enabled: true }
];
const result = convertData(rows, mappings);
expect(result[0].date).toBe('2023-01-01');
});
it('returns unix timestamp when format is timestamp', () => {
const rows: RowData[] = [{ date: '2023-01-01' }];
const mappings: MappingConfig[] = [
{ source: 'date', target: 'date', type: 'date', format: 'timestamp', excludeIfEmpty: false, defaultValue: '', enabled: true }
];
const result = convertData(rows, mappings);
expect(typeof result[0].date).toBe('number');
});
});
describe('template system', () => {
it('exports and applies templates', () => {
const mappings = createDefaultMappings(['姓名', '入职日期']);
mappings[0].target = 'userName';
mappings[1].type = 'date';
mappings[1].format = 'YYYY-MM-DD';
mappings[1].target = 'joinDate';
const template = exportTemplate(mappings);
expect(template).toHaveLength(2);
expect(template[0].target).toBe('userName');
expect(template[1].format).toBe('YYYY-MM-DD');
// Apply to fresh mappings
const freshMappings = createDefaultMappings(['姓名', '入职日期', '备注']);
const applied = applyTemplate(freshMappings, template);
expect(applied[0].target).toBe('userName');
expect(applied[1].type).toBe('date');
expect(applied[2].target).toBe('备注'); // not in template, unchanged
});
});