58 lines
2 KiB
TypeScript
58 lines
2 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { slugify } from '@/lib/utils';
|
|
import { excerptFromBody, extractHeadings, filterPublished, isPublished, readingMinutes } from '@/lib/content';
|
|
|
|
describe('slugify (frontmatter slug)', () => {
|
|
it('produces a url-safe slug', () => {
|
|
expect(slugify('Hello, World!')).toBe('hello-world');
|
|
expect(slugify(' Already-slug ')).toBe('already-slug');
|
|
expect(slugify('Prisma + Next.js: a guide')).toBe('prisma-next-js-a-guide');
|
|
});
|
|
});
|
|
|
|
describe('readingMinutes', () => {
|
|
it('never returns less than one minute', () => {
|
|
expect(readingMinutes('short')).toBe(1);
|
|
});
|
|
|
|
it('rounds to the nearest minute at ~200 words per minute', () => {
|
|
const body = Array.from({ length: 600 }, () => 'word').join(' ');
|
|
expect(readingMinutes(body)).toBe(3);
|
|
});
|
|
});
|
|
|
|
describe('draft filtering', () => {
|
|
it('keeps only published items', () => {
|
|
const items = [
|
|
{ slug: 'a', status: 'published' },
|
|
{ slug: 'b', status: 'draft' },
|
|
{ slug: 'c', status: 'published' },
|
|
];
|
|
expect(filterPublished(items).map((i) => i.slug)).toEqual(['a', 'c']);
|
|
expect(isPublished('published')).toBe(true);
|
|
expect(isPublished('draft')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('extractHeadings (table of contents)', () => {
|
|
it('collects h2/h3 headings with anchors', () => {
|
|
const body = ['# Title', 'intro', '', '## Before you ship', 'text', '', '### Details', 'more'].join('\n');
|
|
expect(extractHeadings(body)).toEqual([
|
|
{ id: 'before-you-ship', text: 'Before you ship', level: 2 },
|
|
{ id: 'details', text: 'Details', level: 3 },
|
|
]);
|
|
});
|
|
|
|
it('de-duplicates repeated heading anchors', () => {
|
|
const body = ['## Setup', 'a', '', '## Setup', 'b'].join('\n');
|
|
expect(extractHeadings(body).map((h) => h.id)).toEqual(['setup', 'setup-1']);
|
|
});
|
|
});
|
|
|
|
describe('excerptFromBody', () => {
|
|
it('strips markdown and truncates', () => {
|
|
const excerpt = excerptFromBody('# Title\n\nSome **bold** text with `code`.');
|
|
expect(excerpt).toBe('Title Some bold text with code.');
|
|
});
|
|
});
|