- node --test over routes, client (fake fetcher, include_empty=1), pagination, htmlGate (Go FormatHTML parity cases), sitemap, seo and pl/en i18n parity - package script test and a Testing line in the README
95 lines
3.8 KiB
TypeScript
95 lines
3.8 KiB
TypeScript
// SEO values for Journal pages: description fallback, absolute og:image and
|
|
// list titles.
|
|
import { test } from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { absoluteUrl, htmlToText, listTitle, postSeoMeta, truncateText } from '../app/utils/seo.ts'
|
|
import type { JournalPost } from '../app/utils/types.ts'
|
|
|
|
function post(extra: Partial<JournalPost> = {}): JournalPost {
|
|
return {
|
|
id: 1,
|
|
title: 'Najnowsze Badania nad Cordycepsem',
|
|
slug: 'blogbadania-nad-cordycepsem',
|
|
excerpt: null,
|
|
content: null,
|
|
content_html: null,
|
|
reading_time: 1,
|
|
published: true,
|
|
published_at: '2024-06-12T06:00:00+00:00',
|
|
is_pinned: false,
|
|
metadata: null,
|
|
sources: null,
|
|
author: null,
|
|
categories: [],
|
|
tags: [],
|
|
featured_images: [],
|
|
featured_image_url: null,
|
|
translations: null,
|
|
created_at: '2024-06-12T06:00:00+00:00',
|
|
updated_at: '2024-06-13T06:00:00+00:00',
|
|
...extra,
|
|
}
|
|
}
|
|
|
|
test('htmlToText drops tags, scripts and styles and decodes entities', () => {
|
|
assert.equal(
|
|
htmlToText('<p>A &<b> "c" 'd'</p><script>x()</script><style>p{}</style>\n<p>e</p>'),
|
|
'A &<b> "c" \'d\' e',
|
|
)
|
|
assert.equal(htmlToText(null), '')
|
|
})
|
|
|
|
test('truncateText keeps short text and cuts long text at a word with an ellipsis', () => {
|
|
assert.equal(truncateText('krótki', 160), 'krótki')
|
|
const long = 'słowo '.repeat(40).trim()
|
|
const cut = truncateText(long, 160)
|
|
assert.ok(cut.length <= 160)
|
|
assert.ok(cut.endsWith('…'))
|
|
assert.ok(!cut.endsWith(' …'))
|
|
assert.equal(truncateText('x'.repeat(200), 10), `${'x'.repeat(9)}…`)
|
|
})
|
|
|
|
test('the excerpt is the description when set', () => {
|
|
const meta = postSeoMeta(post({ excerpt: 'Co mówi nauka.', content_html: '<p>Treść</p>' }))
|
|
assert.equal(meta.description, 'Co mówi nauka.')
|
|
assert.equal(meta.ogDescription, 'Co mówi nauka.')
|
|
assert.equal(meta.title, 'Najnowsze Badania nad Cordycepsem')
|
|
assert.equal(meta.ogTitle, meta.title)
|
|
assert.equal(meta.ogType, 'article')
|
|
})
|
|
|
|
test('without an excerpt the description is the first 160 characters of the body text', () => {
|
|
const body = `<p>${'Grzyby funkcjonalne wspierają zdrowie. '.repeat(10)}</p>`
|
|
const meta = postSeoMeta(post({ excerpt: '', content_html: body }))
|
|
assert.ok(meta.description.length <= 160)
|
|
assert.ok(meta.description.startsWith('Grzyby funkcjonalne wspierają zdrowie.'))
|
|
assert.ok(!meta.description.includes('<'))
|
|
})
|
|
|
|
test('og:image becomes absolute against the site URL', () => {
|
|
const url = '/storage/app/uploads/public/665/f1e/2a3/665f1e2a3b4c5d6e7f8091.png'
|
|
assert.equal(postSeoMeta(post({ featured_image_url: url }), 'https://grzybyfunkcjonalne.pl/').ogImage, `https://grzybyfunkcjonalne.pl${url}`)
|
|
assert.equal(postSeoMeta(post({ featured_image_url: 'https://cdn.test/a.png' }), 'https://x.test').ogImage, 'https://cdn.test/a.png')
|
|
assert.equal(postSeoMeta(post()).ogImage, undefined)
|
|
})
|
|
|
|
test('article times come from published_at and updated_at', () => {
|
|
const meta = postSeoMeta(post())
|
|
assert.equal(meta.articlePublishedTime, '2024-06-12T06:00:00+00:00')
|
|
assert.equal(meta.articleModifiedTime, '2024-06-13T06:00:00+00:00')
|
|
const bare = postSeoMeta(post({ published_at: null, updated_at: null }))
|
|
assert.equal(bare.articlePublishedTime, undefined)
|
|
assert.equal(bare.articleModifiedTime, undefined)
|
|
})
|
|
|
|
test('absoluteUrl passes through absolute URLs and a missing site URL', () => {
|
|
assert.equal(absoluteUrl('a.png', 'https://x.test'), 'https://x.test/a.png')
|
|
assert.equal(absoluteUrl('HTTPS://y.test/a.png', 'https://x.test'), 'HTTPS://y.test/a.png')
|
|
assert.equal(absoluteUrl('/a.png', null), '/a.png')
|
|
})
|
|
|
|
test('listTitle adds the page title only after page 1', () => {
|
|
assert.equal(listTitle('Artykuły', 1, 'Strona 1'), 'Artykuły')
|
|
assert.equal(listTitle('Artykuły', 2, 'Strona 2'), 'Artykuły · Strona 2')
|
|
})
|