205 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			205 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
#!/usr/bin/env node
 | 
						|
 | 
						|
/**
 | 
						|
 * Unit tests for Excalidraw Obsidian format utilities
 | 
						|
 * Run with: node server/excalidraw-obsidian.test.mjs
 | 
						|
 */
 | 
						|
 | 
						|
import assert from 'assert';
 | 
						|
import {
 | 
						|
  parseObsidianExcalidrawMd,
 | 
						|
  parseFlatJson,
 | 
						|
  toObsidianExcalidrawMd,
 | 
						|
  extractFrontMatter,
 | 
						|
  parseExcalidrawAny,
 | 
						|
  isValidExcalidrawScene
 | 
						|
} from './excalidraw-obsidian.mjs';
 | 
						|
 | 
						|
let passed = 0;
 | 
						|
let failed = 0;
 | 
						|
 | 
						|
function test(name, fn) {
 | 
						|
  try {
 | 
						|
    fn();
 | 
						|
    console.log(`✅ ${name}`);
 | 
						|
    passed++;
 | 
						|
  } catch (error) {
 | 
						|
    console.error(`❌ ${name}`);
 | 
						|
    console.error(`   ${error.message}`);
 | 
						|
    failed++;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Sample data
 | 
						|
const sampleScene = {
 | 
						|
  elements: [
 | 
						|
    { id: '1', type: 'rectangle', x: 100, y: 100, width: 200, height: 100 }
 | 
						|
  ],
 | 
						|
  appState: { viewBackgroundColor: '#ffffff' },
 | 
						|
  files: {}
 | 
						|
};
 | 
						|
 | 
						|
const sampleFrontMatter = `---
 | 
						|
excalidraw-plugin: parsed
 | 
						|
tags: [excalidraw]
 | 
						|
---`;
 | 
						|
 | 
						|
console.log('🧪 Running Excalidraw Obsidian Format Tests\n');
 | 
						|
 | 
						|
// Test: extractFrontMatter
 | 
						|
test('extractFrontMatter - extracts front matter', () => {
 | 
						|
  const md = `---
 | 
						|
excalidraw-plugin: parsed
 | 
						|
---
 | 
						|
Content here`;
 | 
						|
  const result = extractFrontMatter(md);
 | 
						|
  assert.ok(result);
 | 
						|
  assert.ok(result.includes('excalidraw-plugin'));
 | 
						|
});
 | 
						|
 | 
						|
test('extractFrontMatter - returns null when no front matter', () => {
 | 
						|
  const md = 'Just some content';
 | 
						|
  const result = extractFrontMatter(md);
 | 
						|
  assert.strictEqual(result, null);
 | 
						|
});
 | 
						|
 | 
						|
// Test: toObsidianExcalidrawMd
 | 
						|
test('toObsidianExcalidrawMd - creates valid markdown', () => {
 | 
						|
  const md = toObsidianExcalidrawMd(sampleScene);
 | 
						|
  assert.ok(md.includes('---'));
 | 
						|
  assert.ok(md.includes('excalidraw-plugin'));
 | 
						|
  assert.ok(md.includes('```compressed-json'));
 | 
						|
  assert.ok(md.includes('# Excalidraw Data'));
 | 
						|
});
 | 
						|
 | 
						|
test('toObsidianExcalidrawMd - preserves existing front matter', () => {
 | 
						|
  const customFrontMatter = `---
 | 
						|
excalidraw-plugin: parsed
 | 
						|
tags: [custom, test]
 | 
						|
---`;
 | 
						|
  const md = toObsidianExcalidrawMd(sampleScene, customFrontMatter);
 | 
						|
  assert.ok(md.includes('tags: [custom, test]'));
 | 
						|
});
 | 
						|
 | 
						|
// Test: parseObsidianExcalidrawMd round-trip
 | 
						|
test('parseObsidianExcalidrawMd - round-trip conversion', () => {
 | 
						|
  const md = toObsidianExcalidrawMd(sampleScene);
 | 
						|
  const parsed = parseObsidianExcalidrawMd(md);
 | 
						|
  
 | 
						|
  assert.ok(parsed);
 | 
						|
  assert.ok(Array.isArray(parsed.elements));
 | 
						|
  assert.strictEqual(parsed.elements.length, 1);
 | 
						|
  assert.strictEqual(parsed.elements[0].type, 'rectangle');
 | 
						|
});
 | 
						|
 | 
						|
// Test: parseFlatJson
 | 
						|
test('parseFlatJson - parses valid JSON', () => {
 | 
						|
  const json = JSON.stringify(sampleScene);
 | 
						|
  const parsed = parseFlatJson(json);
 | 
						|
  
 | 
						|
  assert.ok(parsed);
 | 
						|
  assert.ok(Array.isArray(parsed.elements));
 | 
						|
  assert.strictEqual(parsed.elements.length, 1);
 | 
						|
});
 | 
						|
 | 
						|
test('parseFlatJson - returns null for invalid JSON', () => {
 | 
						|
  const parsed = parseFlatJson('not valid json');
 | 
						|
  assert.strictEqual(parsed, null);
 | 
						|
});
 | 
						|
 | 
						|
test('parseFlatJson - returns null for JSON without elements', () => {
 | 
						|
  const parsed = parseFlatJson('{"foo": "bar"}');
 | 
						|
  assert.strictEqual(parsed, null);
 | 
						|
});
 | 
						|
 | 
						|
// Test: parseExcalidrawAny
 | 
						|
test('parseExcalidrawAny - parses Obsidian format', () => {
 | 
						|
  const md = toObsidianExcalidrawMd(sampleScene);
 | 
						|
  const parsed = parseExcalidrawAny(md);
 | 
						|
  
 | 
						|
  assert.ok(parsed);
 | 
						|
  assert.ok(Array.isArray(parsed.elements));
 | 
						|
});
 | 
						|
 | 
						|
test('parseExcalidrawAny - parses flat JSON', () => {
 | 
						|
  const json = JSON.stringify(sampleScene);
 | 
						|
  const parsed = parseExcalidrawAny(json);
 | 
						|
  
 | 
						|
  assert.ok(parsed);
 | 
						|
  assert.ok(Array.isArray(parsed.elements));
 | 
						|
});
 | 
						|
 | 
						|
test('parseExcalidrawAny - returns null for invalid content', () => {
 | 
						|
  const parsed = parseExcalidrawAny('invalid content');
 | 
						|
  assert.strictEqual(parsed, null);
 | 
						|
});
 | 
						|
 | 
						|
// Test: isValidExcalidrawScene
 | 
						|
test('isValidExcalidrawScene - validates correct structure', () => {
 | 
						|
  assert.strictEqual(isValidExcalidrawScene(sampleScene), true);
 | 
						|
});
 | 
						|
 | 
						|
test('isValidExcalidrawScene - rejects invalid structure', () => {
 | 
						|
  assert.strictEqual(isValidExcalidrawScene({}), false);
 | 
						|
  assert.strictEqual(isValidExcalidrawScene({ elements: 'not an array' }), false);
 | 
						|
  assert.strictEqual(isValidExcalidrawScene(null), false);
 | 
						|
});
 | 
						|
 | 
						|
// Test: Empty scene handling
 | 
						|
test('toObsidianExcalidrawMd - handles empty scene', () => {
 | 
						|
  const emptyScene = { elements: [], appState: {}, files: {} };
 | 
						|
  const md = toObsidianExcalidrawMd(emptyScene);
 | 
						|
  const parsed = parseObsidianExcalidrawMd(md);
 | 
						|
  
 | 
						|
  assert.ok(parsed);
 | 
						|
  assert.ok(Array.isArray(parsed.elements));
 | 
						|
  assert.strictEqual(parsed.elements.length, 0);
 | 
						|
});
 | 
						|
 | 
						|
// Test: Large scene handling
 | 
						|
test('toObsidianExcalidrawMd - handles large scene', () => {
 | 
						|
  const largeScene = {
 | 
						|
    elements: Array.from({ length: 100 }, (_, i) => ({
 | 
						|
      id: `${i}`,
 | 
						|
      type: 'rectangle',
 | 
						|
      x: i * 10,
 | 
						|
      y: i * 10,
 | 
						|
      width: 50,
 | 
						|
      height: 50
 | 
						|
    })),
 | 
						|
    appState: {},
 | 
						|
    files: {}
 | 
						|
  };
 | 
						|
  
 | 
						|
  const md = toObsidianExcalidrawMd(largeScene);
 | 
						|
  const parsed = parseObsidianExcalidrawMd(md);
 | 
						|
  
 | 
						|
  assert.ok(parsed);
 | 
						|
  assert.strictEqual(parsed.elements.length, 100);
 | 
						|
});
 | 
						|
 | 
						|
// Test: Special characters in scene
 | 
						|
test('toObsidianExcalidrawMd - handles special characters', () => {
 | 
						|
  const sceneWithSpecialChars = {
 | 
						|
    elements: [
 | 
						|
      { id: '1', type: 'text', text: 'Hello "World" & <test>' }
 | 
						|
    ],
 | 
						|
    appState: {},
 | 
						|
    files: {}
 | 
						|
  };
 | 
						|
  
 | 
						|
  const md = toObsidianExcalidrawMd(sceneWithSpecialChars);
 | 
						|
  const parsed = parseObsidianExcalidrawMd(md);
 | 
						|
  
 | 
						|
  assert.ok(parsed);
 | 
						|
  assert.strictEqual(parsed.elements[0].text, 'Hello "World" & <test>');
 | 
						|
});
 | 
						|
 | 
						|
// Summary
 | 
						|
console.log('\n━'.repeat(30));
 | 
						|
console.log(`✅ Passed: ${passed}`);
 | 
						|
console.log(`❌ Failed: ${failed}`);
 | 
						|
console.log('━'.repeat(30));
 | 
						|
 | 
						|
process.exit(failed > 0 ? 1 : 0);
 |