76 lines
2.2 KiB
TypeScript
76 lines
2.2 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { EMPTY_SEO } from '@/lib/articleSeo'
|
|
import {
|
|
applyTitleTemplate,
|
|
bodyText,
|
|
firstSentence,
|
|
previewTitle,
|
|
siteDisplayName,
|
|
socialTitle,
|
|
} from '@/lib/seoPreview'
|
|
import type { Site } from '@/composables/useSites'
|
|
|
|
const site = {
|
|
id: 1,
|
|
name: 'Renew',
|
|
key: 'renew',
|
|
base_url: 'https://renew.example',
|
|
default_social_image_id: null,
|
|
default_robots: 'index',
|
|
locale: null,
|
|
site_name: '',
|
|
title_template: '%title% | %site%',
|
|
is_default: true,
|
|
article_count: 1,
|
|
} as Site
|
|
|
|
describe('applyTitleTemplate', () => {
|
|
it('replaces every occurrence in a single pass', () => {
|
|
expect(applyTitleTemplate('%site%: %title% (%title%)', 'A', 'S')).toBe('S: A (A)')
|
|
})
|
|
|
|
it('does not expand replacement patterns or substitute tokens inside the title', () => {
|
|
expect(applyTitleTemplate('%title% | %site%', "Cost $& $' $` %site%", 'Renew')).toBe(
|
|
"Cost $& $' $` %site% | Renew",
|
|
)
|
|
})
|
|
|
|
it('falls back to the default template and trims', () => {
|
|
expect(applyTitleTemplate('', 'A', '')).toBe('A |')
|
|
})
|
|
})
|
|
|
|
describe('bodyText', () => {
|
|
it('separates block elements with a space', () => {
|
|
expect(bodyText('<p>One.</p><p>Two</p>')).toBe('One. Two')
|
|
expect(firstSentence('<p>One.</p><p>Two</p>')).toBe('One.')
|
|
})
|
|
|
|
it('skips script and style text', () => {
|
|
expect(bodyText('<style>p{}</style><p>Kept</p><script>alert(1)</script>')).toBe('Kept')
|
|
})
|
|
|
|
it('does not run markup', () => {
|
|
const img = '<img src=x onerror="document.body.dataset.ran=1">'
|
|
bodyText(img)
|
|
expect(document.body.dataset.ran).toBeUndefined()
|
|
})
|
|
})
|
|
|
|
describe('titles', () => {
|
|
const input = { seo: { ...EMPTY_SEO }, title: 'Article', body: '', site }
|
|
|
|
it('uses the site name, then the site key name, for the template', () => {
|
|
expect(siteDisplayName(site)).toBe('Renew')
|
|
expect(previewTitle(input)).toBe('Article | Renew')
|
|
})
|
|
|
|
it('falls back to the templated title for the social title', () => {
|
|
expect(socialTitle(input)).toBe('Article | Renew')
|
|
expect(socialTitle({ ...input, seo: { ...EMPTY_SEO, seo_title: 'Meta' } })).toBe(
|
|
'Meta | Renew',
|
|
)
|
|
expect(socialTitle({ ...input, seo: { ...EMPTY_SEO, social_title: 'Own' } })).toBe('Own')
|
|
})
|
|
})
|