import { describe, it, expect } from 'vitest';
import { resolve } from 'path';
import {
convertMdxToMarkdown,
searchInMdxFile,
extractFrontmatter
} from '../src/utils/mdx-processor.js';
const FIXTURES_DIR = resolve(process.cwd(), 'tests', 'fixtures');
describe('MDX Processor', () => {
describe('convertMdxToMarkdown', () => {
it('should convert basic MDX file to markdown', async () => {
const filePath = resolve(FIXTURES_DIR, 'basic-with-frontmatter.mdx');
const result = await convertMdxToMarkdown(filePath);
expect(result).toBeTruthy();
expect(result).toContain('Getting Started with MDX');
expect(result).toContain('Installation');
expect(typeof result).toBe('string');
});
it('should convert MDX with JSX components to markdown', async () => {
const filePath = resolve(FIXTURES_DIR, 'simple-jsx.mdx');
const result = await convertMdxToMarkdown(filePath);
expect(result).toBeTruthy();
expect(result).toContain('Interactive Documentation');
expect(typeof result).toBe('string');
});
it('should handle MDX without frontmatter', async () => {
const filePath = resolve(FIXTURES_DIR, 'no-frontmatter.mdx');
const result = await convertMdxToMarkdown(filePath);
expect(result).toBeTruthy();
expect(result).toContain('Simple MDX Document');
expect(result).toContain('Section 1');
expect(typeof result).toBe('string');
});
it('should throw error for non-existent file', async () => {
const filePath = resolve(FIXTURES_DIR, 'nonexistent.mdx');
await expect(convertMdxToMarkdown(filePath)).rejects.toThrow();
});
});
describe('searchInMdxFile', () => {
it('should find exact matches in file', async () => {
const filePath = resolve(FIXTURES_DIR, 'search-test.mdx');
const results = await searchInMdxFile(filePath, 'Authentication', 2);
expect(results.length).toBeGreaterThan(0); // At least one match
expect(results[0].content).toContain('Authentication');
expect(results[0].lineNumber).toBeGreaterThan(0);
});
it('should include context lines before and after match', async () => {
const filePath = resolve(FIXTURES_DIR, 'search-test.mdx');
const results = await searchInMdxFile(filePath, 'API Keys', 2);
expect(results.length).toBeGreaterThan(0);
const match = results[0];
expect(match.context.before).toBeDefined();
expect(match.context.after).toBeDefined();
expect(match.context.before.length).toBeLessThanOrEqual(2);
expect(match.context.after.length).toBeLessThanOrEqual(2);
});
it('should handle different context line counts', async () => {
const filePath = resolve(FIXTURES_DIR, 'search-test.mdx');
const results1 = await searchInMdxFile(filePath, 'OAuth', 1);
const results2 = await searchInMdxFile(filePath, 'OAuth', 3);
expect(results1.length).toBeGreaterThan(0);
expect(results2.length).toBeGreaterThan(0);
const match1 = results1[0];
const match2 = results2[0];
expect(match1.context.before.length).toBeLessThanOrEqual(1);
expect(match2.context.before.length).toBeLessThanOrEqual(3);
});
it('should return empty array when no matches found', async () => {
const filePath = resolve(FIXTURES_DIR, 'search-test.mdx');
const results = await searchInMdxFile(filePath, 'NONEXISTENTTEXT12345', 2);
expect(results).toEqual([]);
});
it('should find multiple occurrences of same term', async () => {
const filePath = resolve(FIXTURES_DIR, 'search-test.mdx');
const results = await searchInMdxFile(filePath, 'API', 1);
expect(results.length).toBeGreaterThan(3); // "API" appears many times
results.forEach(match => {
expect(match.content).toContain('API');
});
});
it('should handle context at file boundaries', async () => {
const filePath = resolve(FIXTURES_DIR, 'no-frontmatter.mdx');
const results = await searchInMdxFile(filePath, 'Simple MDX Document', 5);
expect(results.length).toBeGreaterThan(0);
const match = results[0];
// First line should have no context before
expect(match.context.before.length).toBe(0);
});
});
describe('extractFrontmatter', () => {
it('should extract valid frontmatter from MDX file', async () => {
const filePath = resolve(FIXTURES_DIR, 'basic-with-frontmatter.mdx');
const result = await extractFrontmatter(filePath);
expect(result).not.toBeNull();
expect(result).toHaveProperty('title');
expect(result?.title).toBe('Getting Started Guide');
expect(result?.author).toBe('John Doe');
expect(result?.date).toBe('2025-01-15');
});
it('should parse different data types in frontmatter', async () => {
const filePath = resolve(FIXTURES_DIR, 'basic-with-frontmatter.mdx');
const result = await extractFrontmatter(filePath);
expect(result).not.toBeNull();
expect(result?.published).toBe(true); // Boolean
expect(typeof result?.title).toBe('string'); // String
});
it('should handle MDX files without frontmatter', async () => {
const filePath = resolve(FIXTURES_DIR, 'no-frontmatter.mdx');
const result = await extractFrontmatter(filePath);
expect(result).toBeNull();
});
it('should extract frontmatter with multiple fields', async () => {
const filePath = resolve(FIXTURES_DIR, 'search-test.mdx');
const result = await extractFrontmatter(filePath);
expect(result).not.toBeNull();
expect(result).toHaveProperty('title');
expect(result).toHaveProperty('category');
expect(result).toHaveProperty('keywords');
expect(result?.title).toBe('API Reference Documentation');
expect(result?.category).toBe('reference');
});
it('should handle frontmatter with quoted strings', async () => {
const filePath = resolve(FIXTURES_DIR, 'simple-jsx.mdx');
const result = await extractFrontmatter(filePath);
expect(result).not.toBeNull();
expect(result?.title).toBe('Simple JSX Example');
expect(result?.type).toBe('demo');
});
it('should handle frontmatter with version values', async () => {
const filePath = resolve(FIXTURES_DIR, 'simple-jsx.mdx');
const result = await extractFrontmatter(filePath);
expect(result).not.toBeNull();
// Verify the fields exist
expect(result?.title).toBeDefined();
expect(result?.type).toBe('demo');
});
});
});