import { describe, it, expect } from 'vitest';
import { extractSection, upsertSection } from './extractSections';
import { detectActiveTabs } from './detectActiveTabs';
import { processCircuitEmbeds, processFlowchartEmbeds, processEmbedEmbeds } from './processEmbeds';
import { parseSlides } from './parseSlides';
import { parseFlashcards } from './parseFlashcards';
import { renderMarkdownPreview } from './index';
describe('Markdown Renderer & Extractor Tests', () => {
describe('extractSection', () => {
it('should extract section between markers and return remaining text', () => {
const input = 'Before\n---EXPECTED_OUTPUT---\nexpected content\n---END_EXPECTED_OUTPUT---\nAfter';
const [extracted, remaining] = extractSection(input, '---EXPECTED_OUTPUT---', '---END_EXPECTED_OUTPUT---');
expect(extracted).toBe('expected content');
expect(remaining).toBe('Before\n\nAfter');
});
it('should return empty string and original text if markers are not present', () => {
const input = 'Some random content without markers';
const [extracted, remaining] = extractSection(input, '---START---', '---END---');
expect(extracted).toBe('');
expect(remaining).toBe(input);
});
});
describe('upsertSection', () => {
it('should replace existing section content while preserving surrounding text', () => {
const input = 'Header\n---INITIAL_CODE_ARDUINO---\nold code\n---END_INITIAL_CODE_ARDUINO---\nFooter';
const result = upsertSection(input, '---INITIAL_CODE_ARDUINO---', '---END_INITIAL_CODE_ARDUINO---', 'new code\nvoid setup() {}');
expect(result).toBe('Header\n---INITIAL_CODE_ARDUINO---\nnew code\nvoid setup() {}\n---END_INITIAL_CODE_ARDUINO---\nFooter');
});
it('should append section to content if markers do not exist', () => {
const input = 'Header content';
const result = upsertSection(input, '---VELXIO_CIRCUIT---', '---END_VELXIO_CIRCUIT---', '{"board": "arduino:avr:uno"}');
expect(result).toBe('Header content\n\n---VELXIO_CIRCUIT---\n{"board": "arduino:avr:uno"}\n---END_VELXIO_CIRCUIT---\n');
});
});
describe('detectActiveTabs', () => {
it('should detect velxio mode exclusively if INITIAL_CODE_ARDUINO is present', () => {
const input = '---INITIAL_CODE_ARDUINO---\nvoid setup() {}\n---END_INITIAL_CODE_ARDUINO---\n---INITIAL_CODE---\nint main() {}\n---END_INITIAL_CODE---';
const tabs = detectActiveTabs(input);
expect(tabs).toContain('velxio');
expect(tabs).not.toContain('c');
});
it('should detect c and python tabs if present', () => {
const input = '---INITIAL_CODE---\nint main() {}\n---END_INITIAL_CODE---\n---INITIAL_PYTHON---\ndef main(): pass\n---END_INITIAL_PYTHON---';
const tabs = detectActiveTabs(input);
expect(tabs).toContain('c');
expect(tabs).toContain('python');
});
it('should fallback to c tab if no markers match but ---EXERCISE--- is present', () => {
const input = 'Plain lesson here\n---EXERCISE---\nDo this exercise';
const tabs = detectActiveTabs(input);
expect(tabs).toEqual(['c']);
});
});
describe('processCircuitEmbeds', () => {
it('should replace circuit fences with div placeholders', () => {
const input = '```circuit\ncircuit_data_here\n```';
const output = processCircuitEmbeds(input);
expect(output).toContain('class="circuit-embed"');
expect(output).toContain('data-width="100%"');
expect(output).toContain('data-height="400px"');
expect(output).toContain('circuit_data_here');
});
it('should handle height parameter', () => {
const input = '```circuit,500px\ncircuit_data_here\n```';
const output = processCircuitEmbeds(input);
expect(output).toContain('data-height="500px"');
});
it('should handle width and height parameters', () => {
const input = '```circuit,80%,600px\ncircuit_data_here\n```';
const output = processCircuitEmbeds(input);
expect(output).toContain('data-width="80%"');
expect(output).toContain('data-height="600px"');
});
});
describe('processFlowchartEmbeds', () => {
it('should replace flowchart fences with div placeholders', () => {
const input = '```flowchart\nflowchart_data_here\n```';
const output = processFlowchartEmbeds(input);
expect(output).toContain('class="flowchart-embed"');
expect(output).toContain('data-width="100%"');
expect(output).toContain('data-height="400px"');
expect(output).toContain('flowchart_data_here');
});
});
describe('processEmbedEmbeds', () => {
it('should return error div for empty embed', () => {
const input = '```embed\n\n```';
const output = processEmbedEmbeds(input);
expect(output).toContain('embed-error');
expect(output).toContain('Konten embed kosong');
});
it('should sanitize and allow valid https iframe embed', () => {
const input = '```embed\n\n```';
const output = processEmbedEmbeds(input);
expect(output).toContain('