94 lines
3.7 KiB
JavaScript
94 lines
3.7 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { rm, writeFile } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import { after, before, test } from 'node:test';
|
|
import { createContentStore, loadContent, parseFrontmatter, youtubeId } from '../src/content.js';
|
|
import { formatDate, localize, pickLocale } from '../src/i18n.js';
|
|
import { createFixture } from './fixtures.js';
|
|
|
|
let dir;
|
|
before(async () => {
|
|
dir = await createFixture();
|
|
});
|
|
after(() => rm(dir, { recursive: true, force: true }));
|
|
|
|
test('parseFrontmatter splits data and body', () => {
|
|
const { data, body } = parseFrontmatter('---\ntitle: Hi\n---\nBody\n');
|
|
assert.equal(data.title, 'Hi');
|
|
assert.equal(body, 'Body\n');
|
|
assert.deepEqual(parseFrontmatter('no frontmatter').data, {});
|
|
});
|
|
|
|
test('youtubeId understands the usual URL shapes', () => {
|
|
for (const url of [
|
|
'https://youtu.be/dQw4w9WgXcQ',
|
|
'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
|
'https://www.youtube.com/watch?feature=share&v=dQw4w9WgXcQ',
|
|
'https://www.youtube.com/shorts/dQw4w9WgXcQ',
|
|
'https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ',
|
|
]) {
|
|
assert.equal(youtubeId(url), 'dQw4w9WgXcQ', url);
|
|
}
|
|
assert.equal(youtubeId('https://vimeo.com/123'), null);
|
|
});
|
|
|
|
test('i18n helpers', () => {
|
|
assert.equal(localize({ de: 'Hallo', en: 'Hello' }, 'en'), 'Hello');
|
|
assert.equal(localize({ de: 'Nur Deutsch' }, 'en'), 'Nur Deutsch');
|
|
assert.equal(localize('plain', 'de'), 'plain');
|
|
assert.equal(pickLocale('en-US,en;q=0.9,de;q=0.8'), 'en');
|
|
assert.equal(pickLocale('fr-FR,de;q=0.5'), 'de');
|
|
assert.equal(pickLocale('fr'), 'de');
|
|
assert.equal(formatDate(2024, 'de'), '2024');
|
|
assert.equal(formatDate('2026-10', 'de'), 'Oktober 2026');
|
|
assert.equal(formatDate('2026-10-01', 'en'), 'October 2026');
|
|
});
|
|
|
|
test('drafts are hidden unless asked for', async () => {
|
|
const { content } = await loadContent(dir);
|
|
assert.deepEqual(content.projects.map((p) => p.slug), ['alpha']);
|
|
assert.equal(content.homelab, null);
|
|
assert.deepEqual(content.journey.map((e) => e.title), ['Live']);
|
|
|
|
const { content: withDrafts } = await loadContent(dir, { showDrafts: true });
|
|
assert.deepEqual(withDrafts.projects.map((p) => p.slug), ['alpha', 'beta']);
|
|
assert.ok(withDrafts.homelab);
|
|
});
|
|
|
|
test('projects: fallback language, images, video', async () => {
|
|
const { content, warnings } = await loadContent(dir, { showDrafts: true });
|
|
const alpha = content.projects.find((p) => p.slug === 'alpha');
|
|
assert.equal(alpha.text.de.title, 'Alpha');
|
|
assert.equal(alpha.text.en.title, 'Alpha');
|
|
assert.equal(alpha.text.en.fallback, 'de');
|
|
assert.equal(alpha.text.de.fallback, undefined);
|
|
|
|
assert.equal(alpha.cover.width, 1200);
|
|
assert.match(alpha.cover.srcset, /w=480&v=\w+ 480w, .*w=960.* 960w, .*w=1600.* 1200w$/);
|
|
assert.match(alpha.text.de.html, /<img src="\/media\/projects\/alpha\/cover\.png\?w=1600[^"]*" srcset=/);
|
|
assert.deepEqual(alpha.video, {
|
|
type: 'youtube',
|
|
id: 'dQw4w9WgXcQ',
|
|
url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
|
poster: null,
|
|
});
|
|
|
|
const beta = content.projects.find((p) => p.slug === 'beta');
|
|
assert.equal(beta.text.de.fallback, 'en');
|
|
|
|
assert.ok(warnings.some((w) => w.startsWith('projects/broken/meta.yml:')), 'broken project is reported');
|
|
assert.ok(!content.projects.some((p) => p.slug === 'broken'));
|
|
});
|
|
|
|
test('a broken site.yml keeps the previous content', async () => {
|
|
const store = createContentStore({ contentDir: dir, showDrafts: false });
|
|
await store.reload();
|
|
const before = store.get();
|
|
|
|
const file = path.join(dir, 'site.yml');
|
|
await writeFile(file, 'name: [unclosed\n');
|
|
await assert.rejects(store.reload());
|
|
assert.equal(store.get(), before);
|
|
await writeFile(file, 'name: Test\n');
|
|
});
|