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
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'); |
|
}); |
|
});
|
|
|