74 lines
2.8 KiB
TypeScript
74 lines
2.8 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { articleJsonLd, breadcrumbListJsonLd } from '#web-runtime/lib/structured-data';
|
|
import type { PageDocument } from '#web-runtime/types';
|
|
|
|
function page(overrides: Partial<PageDocument> = {}): PageDocument {
|
|
return {
|
|
id: '61',
|
|
status: 'published',
|
|
locale: 'en',
|
|
path: 'blog/api-webhooks',
|
|
groupKey: 'blog-api-webhooks',
|
|
layout: 'blog-item',
|
|
title: 'Working with webhooks',
|
|
seo: { title: 'Working with webhooks — Crux', description: 'How webhooks work.' },
|
|
breadcrumbs: [],
|
|
blocks: [],
|
|
publishedAt: '2026-06-23T13:28:30.697+00:00',
|
|
updatedAt: '2026-08-13T13:28:30.698+00:00',
|
|
...overrides
|
|
};
|
|
}
|
|
|
|
describe('articleJsonLd', () => {
|
|
it('marks up the dates and the hero image', () => {
|
|
const media = { url: 'https://cdn.example.com/hero.jpg', alt: 'Hero' };
|
|
const data = articleJsonLd(page({ hero: { type: 'low', ctaItems: [], media } }));
|
|
|
|
expect(data).toEqual({
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Article',
|
|
'headline': 'Working with webhooks — Crux',
|
|
'description': 'How webhooks work.',
|
|
'datePublished': '2026-06-23T13:28:30.697+00:00',
|
|
'dateModified': '2026-08-13T13:28:30.698+00:00',
|
|
'image': ['https://cdn.example.com/hero.jpg'],
|
|
'inLanguage': 'en'
|
|
});
|
|
});
|
|
|
|
it('emits nothing without a publication date, rather than an Article a crawler will drop', () => {
|
|
expect(articleJsonLd(page({ publishedAt: null }))).toBeNull();
|
|
});
|
|
|
|
it('omits dateModified when the page has never been changed since publishing', () => {
|
|
const published = '2026-06-23T13:28:30.697+00:00';
|
|
const data = articleJsonLd(page({ publishedAt: published, updatedAt: published }));
|
|
|
|
expect(data).not.toHaveProperty('dateModified');
|
|
expect(data).toMatchObject({ datePublished: published });
|
|
});
|
|
|
|
it('falls back to the page title and omits fields the page does not have', () => {
|
|
const data = articleJsonLd(page({ seo: { title: '', description: '' } }));
|
|
|
|
expect(data).toMatchObject({ headline: 'Working with webhooks' });
|
|
expect(data).not.toHaveProperty('description');
|
|
expect(data).not.toHaveProperty('image');
|
|
});
|
|
});
|
|
|
|
describe('breadcrumbListJsonLd', () => {
|
|
it('numbers the trail from one and leaves the current page without a url', () => {
|
|
const data = breadcrumbListJsonLd([
|
|
{ label: 'Home', href: '/en' },
|
|
{ label: 'Blog', href: '/en/blog' },
|
|
{ label: 'Working with webhooks', href: '/en/blog/api-webhooks' }
|
|
]) as { itemListElement: Array<Record<string, unknown>> };
|
|
|
|
expect(data.itemListElement.map((item) => item['position'])).toEqual([1, 2, 3]);
|
|
expect(data.itemListElement[0]).toHaveProperty('item');
|
|
expect(data.itemListElement[2]).not.toHaveProperty('item');
|
|
});
|
|
});
|