refac: missing mutation tests, spa specs, checks shown to pass, touch targets, catalogue entry, production code
This commit is contained in:
1 parent
7c15206170
commit
3e02e14da4
48 files changed
+2173
-83
No files matched your search
@@ -0,0 +1,137 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { flushPromises } from '@vue/test-utils'
|
||||
import { initializeLocale } from '@/i18n'
|
||||
import type { LocalizedSeoContext } from '@/lib/localizedSeo'
|
||||
import type { ResolvedSeo } from '@/lib/seoTypes'
|
||||
import router from '@/router'
|
||||
import SeoLanguageCards from '../SeoLanguageCards.vue'
|
||||
import { byText, mountInApp, text, unmountApp } from './directoryKit'
|
||||
|
||||
const PATTERN = 'https://journal.example.com/{lang}/{slug}'
|
||||
const CANONICAL = 'https://journal.example.com/fr/comment-nous-chiffrons-une-renovation'
|
||||
|
||||
const ALTERNATES = [
|
||||
{
|
||||
id: 10,
|
||||
lang: 'en',
|
||||
story_id: 5,
|
||||
slug: 'how-we-price-a-bathroom-renovation',
|
||||
url: 'https://journal.example.com/en/how-we-price-a-bathroom-renovation',
|
||||
},
|
||||
{ id: 11, lang: 'de', story_id: 5, slug: 'so-kalkulieren-wir-eine-badsanierung', url: null },
|
||||
]
|
||||
|
||||
function resolved(locale = 'fr_FR'): ResolvedSeo {
|
||||
return {
|
||||
title: 'Couts de renovation | Journal',
|
||||
description: '',
|
||||
canonical_url: CANONICAL,
|
||||
robots: 'index, follow',
|
||||
og: {
|
||||
type: 'article',
|
||||
title: '',
|
||||
description: '',
|
||||
image: '',
|
||||
image_alt: '',
|
||||
url: '',
|
||||
site_name: 'Journal',
|
||||
locale,
|
||||
},
|
||||
twitter: { card: 'summary', title: '', description: '', image: '', image_alt: '' },
|
||||
image: { url: '', alt: '', source: 'none' },
|
||||
authors: [],
|
||||
published_at: null,
|
||||
modified_at: '2026-09-26T11:02:00Z',
|
||||
fallbacks: { title: 'title', description: 'none', image: 'none', canonical: 'pattern' },
|
||||
json_ld: {},
|
||||
alternates: ALTERNATES,
|
||||
} as ResolvedSeo
|
||||
}
|
||||
|
||||
function context(overrides: Partial<LocalizedSeoContext> = {}): LocalizedSeoContext {
|
||||
return {
|
||||
lang: 'fr',
|
||||
siteName: 'Journal',
|
||||
siteKey: 'journal',
|
||||
pattern: PATTERN,
|
||||
defaultLang: 'en',
|
||||
disabledLangs: ['es'],
|
||||
published: true,
|
||||
socialState: 'derived',
|
||||
resolved: resolved(),
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
function card(id: string) {
|
||||
return document.body.querySelector(`[data-testid="${id}"]`)
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear()
|
||||
initializeLocale()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
unmountApp()
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
describe('Search and sharing cards for one language', () => {
|
||||
it('shows the canonical with its source note', async () => {
|
||||
await mountInApp(SeoLanguageCards, { context: context() })
|
||||
|
||||
const canonical = text(card('seo-canonical-card'))
|
||||
expect(canonical).toContain('Canonical')
|
||||
expect(canonical).toContain(CANONICAL)
|
||||
expect(canonical).toContain(`Built from the Public URL pattern ${PATTERN}.`)
|
||||
})
|
||||
|
||||
it('lists the published alternates with their URL, or their slug without one, and the disabled note', async () => {
|
||||
await mountInApp(SeoLanguageCards, { context: context() })
|
||||
|
||||
const rows = [...document.body.querySelectorAll('[data-testid="seo-alternate-row"]')]
|
||||
expect(rows.map((row) => text(row))).toEqual([
|
||||
'en https://journal.example.com/en/how-we-price-a-bathroom-renovation Published',
|
||||
'de so-kalkulieren-wir-eine-badsanierung Published',
|
||||
])
|
||||
expect(rows[0]!.querySelector('[aria-label]')!.getAttribute('aria-label')).toBe('English')
|
||||
const alternates = text(card('seo-alternates-card'))
|
||||
expect(alternates).toContain('Alternate languages')
|
||||
expect(alternates).toContain('Published versions in enabled languages only.')
|
||||
expect(alternates).toContain('Drafts and the disabled Spanish language are left out.')
|
||||
})
|
||||
|
||||
it('shows the derived social locale', async () => {
|
||||
await mountInApp(SeoLanguageCards, { context: context() })
|
||||
|
||||
const social = text(card('seo-social-card'))
|
||||
expect(social).toContain('Social locale')
|
||||
expect(social).toContain('og:locale')
|
||||
expect(social).toContain('Derived: fr_FR')
|
||||
})
|
||||
|
||||
it('shows Social locale not set when nothing resolves', async () => {
|
||||
await mountInApp(SeoLanguageCards, { context: context({ resolved: resolved('') }) })
|
||||
|
||||
expect(text(card('seo-social-card'))).toContain('Social locale not set')
|
||||
})
|
||||
|
||||
it('replaces the canonical and alternates with Public URL not configured and opens its settings', async () => {
|
||||
const push = vi.spyOn(router, 'push').mockResolvedValue(undefined)
|
||||
await mountInApp(SeoLanguageCards, { context: context({ pattern: null }) })
|
||||
|
||||
expect(card('seo-canonical-card')).toBeNull()
|
||||
expect(card('seo-alternates-card')).toBeNull()
|
||||
expect(text(document.body)).toContain('Public URL not configured')
|
||||
expect(text(document.body)).toContain(
|
||||
'Add a public URL pattern for Journal to show page and canonical addresses. API links by article ID still work.',
|
||||
)
|
||||
expect(card('seo-social-card')).not.toBeNull()
|
||||
|
||||
byText('button', 'Open Public URL settings')!.click()
|
||||
await flushPromises()
|
||||
|
||||
expect(push).toHaveBeenCalledWith('/settings/sites/journal/public-url')
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user