view markdown_converter/tests/test_wasm.js @ 279:b3b547563ec7

Add Google connector service and agent wiki Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code. Co-authored-by: Copilot <[email protected]> Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
author MrJuneJune <me@mrjunejune.com>
date Mon, 17 Aug 2026 22:22:36 -0700
parents cd35e600ae34
children
line wrap: on
line source

/**
 * Test suite for markdown_to_html WASM module
 */
const fs = require('fs');
// TODO: Fix the rules so that it can do relative import.
const wasm = fs.readFileSync('markdown_converter/wasm/markdown_to_html_wasm.wasm');

let testsPassed = 0;
let testsFailed = 0;

function assertEqual(actual, expected, testName) {
  if (actual === expected) {
    console.log(`✓ ${testName}`);
    testsPassed++;
  } else {
    console.log(`✗ ${testName}`);
    console.log(`  Expected: ${expected}`);
    console.log(`  Actual:   ${actual}`);
    testsFailed++;
  }
}

function assertContains(actual, expected, testName) {
  if (actual.includes(expected)) {
    console.log(`✓ ${testName}`);
    testsPassed++;
  } else {
    console.log(`✗ ${testName}`);
    console.log(`  Expected to contain: ${expected}`);
    console.log(`  Actual: ${actual}`);
    testsFailed++;
  }
}

async function runTests() {
  const module = await WebAssembly.instantiate(wasm, { env: {} });
  const { malloc, heap_reset, markdown_to_html, memory } = module.instance.exports;

  function writeString(str) {
    const encoder = new TextEncoder();
    const bytes = encoder.encode(str + '\0');
    const ptr = malloc(bytes.length);
    new Uint8Array(memory.buffer).set(bytes, ptr);
    return ptr;
  }

  function readString(ptr) {
    const mem = new Uint8Array(memory.buffer);
    let end = ptr;
    while (mem[end] !== 0) end++;
    return new TextDecoder().decode(mem.slice(ptr, end));
  }

  function convert(md) {
    heap_reset();
    const inputPtr = writeString(md);
    const outputPtr = markdown_to_html(inputPtr);
    return readString(outputPtr);
  }

  console.log('Running markdown_to_html WASM tests...\n');

  // Test: Headings
  console.log('--- Headings ---');
  assertEqual(convert('# Hello'), '<h1>Hello</h1>', 'H1 heading');
  assertEqual(convert('## World'), '<h2>World</h2>', 'H2 heading');
  assertEqual(convert('### Level 3'), '<h3>Level 3</h3>', 'H3 heading');
  assertEqual(convert('###### Level 6'), '<h6>Level 6</h6>', 'H6 heading');

  // Test: Inline formatting
  console.log('\n--- Inline Formatting ---');
  assertEqual(convert('**bold**'), '<p><strong>bold</strong></p>', 'Bold with **');
  assertEqual(convert('__bold__'), '<p><strong>bold</strong></p>', 'Bold with __');
  assertEqual(convert('*italic*'), '<p><em>italic</em></p>', 'Italic with *');
  assertEqual(convert('_italic_'), '<p><em>italic</em></p>', 'Italic with _');
  assertEqual(convert('~~strike~~'), '<p><del>strike</del></p>', 'Strikethrough');
  assertEqual(convert('`code`'), '<p><code>code</code></p>', 'Inline code');

  // Test: Links and Images
  console.log('\n--- Links and Images ---');
  assertEqual(convert('[link](http://example.com)'), '<p><a href="http://example.com">link</a></p>', 'Link');
  assertEqual(convert('![alt](http://img.png)'), '<p><img src="http://img.png" alt="alt"></p>', 'Image');

  // Test: Lists
  console.log('\n--- Lists ---');
  assertEqual(convert('- item1\n- item2'), '<ul><li>item1</li><li>item2</li></ul>', 'Unordered list with -');
  assertEqual(convert('* item1\n* item2'), '<ul><li>item1</li><li>item2</li></ul>', 'Unordered list with *');
  assertEqual(convert('1. first\n2. second'), '<ol><li>first</li><li>second</li></ol>', 'Ordered list');

  // Test: Code block
  console.log('\n--- Code Block ---');
  const codeBlock = '```\nfunction test() {\n  return 42;\n}\n```';
  assertContains(convert(codeBlock), '<pre><code>', 'Code block opens');
  assertContains(convert(codeBlock), '</code></pre>', 'Code block closes');

  // Test: Blockquote
  console.log('\n--- Blockquote ---');
  assertEqual(convert('> quote'), '<blockquote>quote </blockquote>', 'Blockquote');

  // Test: Horizontal rule
  console.log('\n--- Horizontal Rule ---');
  assertEqual(convert('---'), '<hr>', 'HR with ---');
  assertEqual(convert('***'), '<hr>', 'HR with ***');
  assertEqual(convert('___'), '<hr>', 'HR with ___');

  // Test: Tables
  console.log('\n--- Tables ---');
  const table = '| Name | Age |\n|------|-----|\n| Alice | 30 |\n| Bob | 25 |';
  const tableHtml = convert(table);
  assertContains(tableHtml, '<table>', 'Table opens');
  assertContains(tableHtml, '</table>', 'Table closes');
  assertContains(tableHtml, '<thead>', 'Table has thead');
  assertContains(tableHtml, '<tbody>', 'Table has tbody');
  assertContains(tableHtml, '<th>Name</th>', 'Table header cell');
  assertContains(tableHtml, '<td>Alice</td>', 'Table body cell');

  // Test: Complex table with inline formatting
  console.log('\n--- Table with Inline Formatting ---');
  const complexTable = '| Feature | Status |\n|---------|--------|\n| **Bold** | *done* |';
  const complexTableHtml = convert(complexTable);
  assertContains(complexTableHtml, '<strong>Bold</strong>', 'Bold in table cell');
  assertContains(complexTableHtml, '<em>done</em>', 'Italic in table cell');

  // Test: HTML escaping
  console.log('\n--- HTML Escaping ---');
  assertContains(convert('<script>'), '&lt;script&gt;', 'Escapes < and >');
  assertContains(convert('a & b'), '&amp;', 'Escapes &');

  // Test: Mixed content
  console.log('\n--- Mixed Content ---');
  const mixed = '# Title\n\nSome **bold** text.\n\n- item 1\n- item 2';
  const mixedHtml = convert(mixed);
  assertContains(mixedHtml, '<h1>Title</h1>', 'Mixed: heading');
  assertContains(mixedHtml, '<strong>bold</strong>', 'Mixed: bold');
  assertContains(mixedHtml, '<ul>', 'Mixed: list');

  // Summary
  console.log('\n========================================');
  console.log(`Tests passed: ${testsPassed}`);
  console.log(`Tests failed: ${testsFailed}`);

  if (testsFailed > 0) {
    process.exit(1);
  }
}

runTests().catch(err => {
  console.error('Test error:', err);
  process.exit(1);
});