Files
2026Technology-Competition/tests/excel-converter.test.ts
T

89 lines
3.6 KiB
TypeScript

import * as assert from 'assert';
import * as path from 'path';
import * as XLSX from 'xlsx';
import { buildMarkdownTable, renderWorkbookToMarkdown } from '../src/rules/converters/excel-converter';
const fixturePath = path.resolve(__dirname, '../../tests/fixtures/galaxy-team-coding-conventions.xlsx');
function workbookWithSheet(name: string, rows: unknown[][]): XLSX.WorkBook {
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet(rows), name);
return wb;
}
suite('ExcelConverter Tests', () => {
test('buildMarkdownTable renders sheet title, header, separator and data rows', () => {
const rows = [
{ 序号: '1', 约定内容: 'no console.log', 是否强制: '强制' },
{ 序号: '2', 约定内容: 'use === only', 是否强制: '建议' },
];
const md = buildMarkdownTable(rows, '编码约定');
const lines = md.split('\n');
assert.strictEqual(lines[0], '## 编码约定');
assert.strictEqual(lines[1], '| 序号 | 约定内容 | 是否强制 |');
assert.strictEqual(lines[2], '| --- | --- | --- |');
assert.strictEqual(lines[3], '| 1 | no console.log | 强制 |');
assert.strictEqual(lines[4], '| 2 | use === only | 建议 |');
});
test('buildMarkdownTable fills missing fields with empty string', () => {
const rows = [
{ id: 'a', note: 'x' },
{ id: 'b' },
];
const md = buildMarkdownTable(rows, 'S');
const lines = md.split('\n');
assert.strictEqual(lines[3], '| a | x |');
assert.strictEqual(lines[4], '| b | |');
});
test('buildMarkdownTable renders columns from union of row keys', () => {
const rows = [
{ 标题: '规则表' },
{ 标题: '1', __EMPTY: 'no console.log', __EMPTY_1: '强制' },
];
const md = buildMarkdownTable(rows, 'S');
const lines = md.split('\n');
assert.strictEqual(lines[1], '| 标题 | __EMPTY | __EMPTY_1 |');
assert.strictEqual(lines[3], '| 规则表 | | |');
assert.strictEqual(lines[4], '| 1 | no console.log | 强制 |');
});
test('renderWorkbookToMarkdown includes all non-empty sheets of galaxy fixture', () => {
const wb = XLSX.readFile(fixturePath);
const md = renderWorkbookToMarkdown(wb);
assert.ok(md, 'galaxy fixture should render non-empty markdown');
assert.match(md, /^## 项目简介$/m);
assert.match(md, /^## 编码约定$/m);
const sheetOrder = md.indexOf('## 项目简介') < md.indexOf('## 编码约定');
assert.ok(sheetOrder, 'sheets should preserve workbook order');
});
test('renderWorkbookToMarkdown keeps galaxy rule content faithful for AI conversion', () => {
const wb = XLSX.readFile(fixturePath);
const md = renderWorkbookToMarkdown(wb)!;
assert.match(md, /console\.log/);
assert.match(md, /===/);
assert.match(md, /var/);
assert.match(md, /SQL/);
assert.match(md, /修订记录/);
assert.match(md, /Vue3/);
assert.match(md, /\| --- \| --- \| --- \| --- \|/);
});
test('renderWorkbookToMarkdown skips empty sheets', () => {
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet([['id', 'severity'], ['no-console', 'warning']]), 'rules');
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet([]), 'empty');
const md = renderWorkbookToMarkdown(wb);
assert.ok(md);
assert.match(md, /## rules/);
assert.doesNotMatch(md, /## empty/);
});
test('renderWorkbookToMarkdown returns null when no sheet has data', () => {
const wb = workbookWithSheet('blank', [[]]);
assert.strictEqual(renderWorkbookToMarkdown(wb), null);
});
});