import { load, CheerioAPI, Cheerio } from 'cheerio'; import { normalizeTableColumnWidths } from './table-utils'; /** * Unit tests for normalizeTableColumnWidths: it writes a `colwidth` attribute * onto the first-row cells of every , deriving widths from a * or the first row, accounting for colspan, and falling back to a default * per-column width (150px) when no pixel widths are present. Re-running the * transform on its own output must be a no-op (idempotent). */ const DEFAULT = 150; function run(html: string): { $: CheerioAPI; $root: Cheerio } { const $ = load(html); const $root = $.root(); normalizeTableColumnWidths($, $root); return { $, $root }; } function firstRowColwidths($root: Cheerio): (string | undefined)[] { return $root .find('table') .first() .find('> tbody > tr, > thead > tr, > tr') .first() .children('td, th') .map((_, el) => (el as any).attribs?.colwidth) .get(); } describe('normalizeTableColumnWidths', () => { it('applies colgroup to the first-row cells', () => { const html = '
' + '' + '' + '
ab
'; const { $root } = run(html); expect(firstRowColwidths($root)).toEqual(['120', '80']); }); it('falls back to first-row cell widths when there is no colgroup', () => { const html = '' + '' + '
ab
'; const { $root } = run(html); expect(firstRowColwidths($root)).toEqual(['200', '90']); }); it('splits a colspan width across the spanned columns', () => { // colspan=2 with width 100 => each derived column ~50, the spanning cell // then gets the joined slice "50,50". const html = '' + '' + '
merged
'; const { $root } = run(html); expect(firstRowColwidths($root)).toEqual(['50,50']); }); it('ignores em/% widths (treated as no width) and applies the default', () => { const html = '' + '' + '
ab
'; const { $root } = run(html); expect(firstRowColwidths($root)).toEqual([String(DEFAULT), String(DEFAULT)]); }); it('applies the default per-column width to a markdown-style table with no widths', () => { const html = '' + '' + '' + '
abc
123
'; const { $root } = run(html); expect(firstRowColwidths($root)).toEqual([ String(DEFAULT), String(DEFAULT), String(DEFAULT), ]); }); it('is idempotent: re-running on its own output changes nothing', () => { const html = '' + '' + '' + '
ab
'; const { $, $root } = run(html); const afterFirst = $root.html(); // second pass normalizeTableColumnWidths($, $root); expect($root.html()).toBe(afterFirst); expect(firstRowColwidths($root)).toEqual(['120', '80']); }); });