A post is a page in the panel's "Blog" category, so it is written, translated, scheduled and reviewed like any page, and the MCP server can publish one the same way. Nothing new in the API. - /blog (/en/blog, /ca/blog): posts newest first, with image, date and excerpt. - A post shows its date and leads back to the blog; its structured data is a BlogPosting. - /blog/rss.xml?lang=xx: one feed per language, announced in <head>. - Posts stay out of the header and the footer, which links the blog once there is any post instead of growing with every one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
57 lines
1.7 KiB
TypeScript
57 lines
1.7 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import type { PublicPage } from './api.types';
|
|
import { byPublication, isBlogPost } from './blog';
|
|
import { buildFeed } from './rss';
|
|
|
|
const post = (id: number, title: string, published_at: string, slug = 'blog') =>
|
|
({
|
|
id,
|
|
title,
|
|
path: `/${title.toLowerCase().replace(/\s/g, '-')}`,
|
|
excerpt: 'Resumen con <etiquetas> & símbolos',
|
|
published_at,
|
|
category: { id: 9, slug, name: 'Blog' },
|
|
}) as unknown as PublicPage;
|
|
|
|
describe('blog', () => {
|
|
it("knows a post by its category, in the visitor's language", () => {
|
|
expect(isBlogPost(post(1, 'Hola', '2026-01-01'), 'es')).toBe(true);
|
|
expect(isBlogPost(post(2, 'Sobre', '2026-01-01', 'colectivo'), 'es')).toBe(
|
|
false,
|
|
);
|
|
});
|
|
|
|
it('orders posts newest first', () => {
|
|
const ordered = byPublication([
|
|
post(1, 'Viejo', '2026-01-01'),
|
|
post(2, 'Nuevo', '2026-09-01'),
|
|
]);
|
|
|
|
expect(ordered.map((p) => p.title)).toEqual(['Nuevo', 'Viejo']);
|
|
});
|
|
});
|
|
|
|
describe('buildFeed', () => {
|
|
const xml = buildFeed(
|
|
'https://pireon.dev',
|
|
'es',
|
|
{ title: 'Pireon — Blog', description: 'Novedades', link: '/blog' },
|
|
[post(1, 'Primer post', '2026-09-01T10:00:00Z')],
|
|
);
|
|
|
|
it('links every item absolutely, with its date', () => {
|
|
expect(xml).toContain('<link>https://pireon.dev/primer-post</link>');
|
|
expect(xml).toContain('<pubDate>Tue, 01 Sep 2026 10:00:00 GMT</pubDate>');
|
|
});
|
|
|
|
it('escapes what it carries and parses as XML', () => {
|
|
expect(xml).toContain('<etiquetas> & símbolos');
|
|
expect(
|
|
new DOMParser()
|
|
.parseFromString(xml, 'application/xml')
|
|
.getElementsByTagName('parsererror'),
|
|
).toHaveLength(0);
|
|
});
|
|
});
|