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); }); });