You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

157 lines
4.7 KiB

import { describe, it, expect } from 'vitest';
import {
buildPublicationAsciiDoc,
renderPublication,
renderPublicationFromEvents,
renderEvent,
toPublicationIndexLike,
} from './publication-helper.js';
const index = {
kind: 30040 as const,
title: 'My Book',
d: 'my-book-v1',
a: ['30041:abc:ch1', '30041:abc:ch2'],
type: 'book',
};
const sections = [
{ address: '30041:abc:ch1', title: 'Chapter One', content: 'First chapter body.' },
{ address: '30041:abc:ch2', title: 'Chapter Two', content: 'Second chapter body.' },
];
describe('buildPublicationAsciiDoc', () => {
it('builds combined AsciiDoc from index and sections', () => {
const adoc = buildPublicationAsciiDoc({ index, sections });
expect(adoc).toContain('= My Book');
expect(adoc).toContain('== Chapter One');
expect(adoc).toContain('First chapter body.');
expect(adoc).toContain('== Chapter Two');
expect(adoc).toContain('Second chapter body.');
});
it('throws if kind is not 30040', () => {
expect(() =>
buildPublicationAsciiDoc({
index: { ...index, kind: 1 as 30040 },
sections,
})
).toThrow('Expected kind 30040');
});
});
describe('renderPublication', () => {
it('returns asciidoc, html, and tableOfContents', () => {
const out = renderPublication({ index, sections });
expect(out.asciidoc).toContain('= My Book');
expect(out.html).toContain('My Book');
expect(out.html).toContain('Chapter One');
expect(out.html).toContain('First chapter body.');
expect(typeof out.tableOfContents).toBe('string');
});
it('can disable toc', () => {
const out = renderPublication({ index, sections }, { toc: false });
expect(out.tableOfContents).toBe('');
});
});
describe('toPublicationIndexLike', () => {
it('parses event-like payload with kind 30040 and title', () => {
const payload = {
kind: 30040,
tags: [
['title', 'Test Pub'],
['d', 'test-d'],
['a', '30041:pk1:d1'],
['a', '30041:pk1:d2'],
['type', 'blog'],
['image', 'https://example.com/cover.png'],
],
};
const parsed = toPublicationIndexLike(payload);
expect(parsed).not.toBeNull();
expect(parsed!.kind).toBe(30040);
expect(parsed!.title).toBe('Test Pub');
expect(parsed!.d).toBe('test-d');
expect(parsed!.a).toEqual(['30041:pk1:d1', '30041:pk1:d2']);
expect(parsed!.type).toBe('blog');
expect(parsed!.image).toBe('https://example.com/cover.png');
});
it('returns null for wrong kind', () => {
expect(toPublicationIndexLike({ kind: 1, tags: [['title', 'X']] })).toBeNull();
});
it('returns null when title is missing', () => {
expect(toPublicationIndexLike({ kind: 30040, tags: [['d', 'x']] })).toBeNull();
});
});
describe('renderEvent', () => {
it('accepts event JSON and returns HTML', () => {
const event = {
kind: 30041,
content: '= One section\n\nSome *bold* text.',
tags: [['title', 'One section']],
pubkey: 'abc',
};
const html = renderEvent(event);
expect(html).toContain('<h1');
expect(html).toContain('One section');
expect(html).toContain('<strong>bold</strong>');
});
it('accepts 30818 wiki event', () => {
const event = { kind: 30818, content: 'Wiki *content*.', tags: [] };
const html = renderEvent(event);
expect(html).toContain('Wiki');
expect(html).toContain('<strong>content</strong>');
});
});
describe('renderPublicationFromEvents', () => {
it('accepts index event + section events JSON and returns one HTML page', () => {
const indexEvent = {
kind: 30040,
content: '',
tags: [
['title', 'My Book'],
['d', 'my-book'],
['a', '30041:pk:ch1'],
['a', '30041:pk:ch2'],
],
pubkey: 'pk',
};
const sectionEvents = [
{
kind: 30041,
content: 'First chapter body.',
tags: [['title', 'Chapter One'], ['d', 'ch1']],
pubkey: 'pk',
},
{
kind: 30041,
content: 'Second chapter body.',
tags: [['title', 'Chapter Two'], ['d', 'ch2']],
pubkey: 'pk',
},
];
const out = renderPublicationFromEvents(indexEvent, sectionEvents);
expect(out.html).toContain('My Book');
expect(out.html).toContain('Chapter One');
expect(out.html).toContain('First chapter body.');
expect(out.html).toContain('Chapter Two');
expect(out.html).toContain('Second chapter body.');
expect(out.asciidoc).toContain('= My Book');
});
it('throws if index event is not kind 30040', () => {
expect(() =>
renderPublicationFromEvents(
{ kind: 1, content: '', tags: [['title', 'X']] },
[]
)
).toThrow('Event kind must be 30040');
});
});