Add initial project files
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user