feat: SEO SPA editor integration
This commit is contained in:
1 parent
eb9876fde3
commit
470584400f
62 files changed
+7471
-58
No files matched your search
@@ -0,0 +1,75 @@
|
||||
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')
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user