131 lines
4.1 KiB
TypeScript
131 lines
4.1 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { normalizeSitemapEntries, sitemapLastPage } from '#web-runtime/data/normalize';
|
|
import { buildSitemap } from '#web-runtime/lib/sitemap';
|
|
import type { SitemapEntry } from '#web-runtime/types';
|
|
|
|
const origin = new URL('https://crux.example.com');
|
|
const publicPath = (locale: string, path: string) => `/${locale}${path ? `/${path}` : ''}`;
|
|
|
|
function entry(overrides: Partial<SitemapEntry> = {}): SitemapEntry {
|
|
return {
|
|
locale: 'en',
|
|
path: 'about',
|
|
groupKey: 'about',
|
|
pageType: 'landing',
|
|
publishedAt: '2026-01-01T00:00:00.000+00:00',
|
|
updatedAt: '2026-02-01T00:00:00.000+00:00',
|
|
...overrides
|
|
};
|
|
}
|
|
|
|
describe('sitemap entry normalization', () => {
|
|
it('reads the backend listing', () => {
|
|
const entries = normalizeSitemapEntries({
|
|
items: [
|
|
{
|
|
id: 7,
|
|
locale: 'en',
|
|
path: '/about/',
|
|
groupKey: 'about',
|
|
pageType: 'landing',
|
|
publishedAt: '2026-01-01T00:00:00.000+00:00',
|
|
updatedAt: null
|
|
}
|
|
]
|
|
});
|
|
|
|
expect(entries).toEqual([
|
|
{
|
|
locale: 'en',
|
|
path: 'about',
|
|
groupKey: 'about',
|
|
pageType: 'landing',
|
|
publishedAt: '2026-01-01T00:00:00.000+00:00',
|
|
updatedAt: null
|
|
}
|
|
]);
|
|
});
|
|
|
|
it('drops entries with no locale, which cannot become a URL', () => {
|
|
expect(normalizeSitemapEntries({ items: [{ path: 'about' }] })).toEqual([]);
|
|
});
|
|
|
|
it('survives a payload that is not a listing at all', () => {
|
|
expect(normalizeSitemapEntries(null)).toEqual([]);
|
|
expect(normalizeSitemapEntries({})).toEqual([]);
|
|
expect(normalizeSitemapEntries({ items: 'nope' })).toEqual([]);
|
|
});
|
|
|
|
it('reads the page count, defaulting to a single page', () => {
|
|
expect(sitemapLastPage({ pagination: { lastPage: 57 } })).toBe(57);
|
|
expect(sitemapLastPage({ pagination: { lastPage: 0 } })).toBe(1);
|
|
expect(sitemapLastPage({})).toBe(1);
|
|
expect(sitemapLastPage(null)).toBe(1);
|
|
});
|
|
});
|
|
|
|
describe('buildSitemap', () => {
|
|
it('emits absolute URLs against the configured origin', () => {
|
|
const [item] = buildSitemap([entry()], origin, publicPath);
|
|
|
|
expect(item?.url).toBe('https://crux.example.com/en/about');
|
|
});
|
|
|
|
it('uses the home path for a page with no path segment', () => {
|
|
const [item] = buildSitemap([entry({ path: '', groupKey: 'home' })], origin, publicPath);
|
|
|
|
expect(item?.url).toBe('https://crux.example.com/en');
|
|
});
|
|
|
|
it('reports lastModified from the update date, falling back to publication', () => {
|
|
const [updated] = buildSitemap([entry()], origin, publicPath);
|
|
const [neverUpdated] = buildSitemap([entry({ updatedAt: null })], origin, publicPath);
|
|
const [undated] = buildSitemap(
|
|
[entry({ updatedAt: null, publishedAt: null })],
|
|
origin,
|
|
publicPath
|
|
);
|
|
|
|
expect(updated?.lastModified).toEqual(new Date('2026-02-01T00:00:00.000+00:00'));
|
|
expect(neverUpdated?.lastModified).toEqual(new Date('2026-01-01T00:00:00.000+00:00'));
|
|
expect(undated?.lastModified).toBeUndefined();
|
|
});
|
|
|
|
it('links translations of the same page to each other', () => {
|
|
const sitemap = buildSitemap(
|
|
[
|
|
entry({ locale: 'en', path: 'about' }),
|
|
entry({ locale: 'de', path: 'ueber-uns' }),
|
|
entry({ locale: 'uk', path: 'pro-nas' })
|
|
],
|
|
origin,
|
|
publicPath
|
|
);
|
|
|
|
expect(sitemap).toHaveLength(3);
|
|
for (const item of sitemap) {
|
|
expect(item.alternates?.languages).toEqual({
|
|
en: 'https://crux.example.com/en/about',
|
|
de: 'https://crux.example.com/de/ueber-uns',
|
|
uk: 'https://crux.example.com/uk/pro-nas'
|
|
});
|
|
}
|
|
});
|
|
|
|
it('omits the alternates block for a page that exists in one locale only', () => {
|
|
const [item] = buildSitemap([entry()], origin, publicPath);
|
|
|
|
expect(item?.alternates).toBeUndefined();
|
|
});
|
|
|
|
it('never groups pages that merely lack a group key', () => {
|
|
const sitemap = buildSitemap(
|
|
[entry({ groupKey: '', path: 'a' }), entry({ groupKey: '', path: 'b', locale: 'de' })],
|
|
origin,
|
|
publicPath
|
|
);
|
|
|
|
expect(sitemap.every((item) => item.alternates === undefined)).toBe(true);
|
|
});
|
|
});
|