mirror of https://github.com/vuejs/vitepress
fix(theme): preserve alt overrides for themed images (#5457)
parent
23361e2493
commit
61c0cbbefe
@ -0,0 +1,38 @@
|
||||
describe('themeable image alt overrides', () => {
|
||||
beforeEach(async () => {
|
||||
await goto('/theme-image/')
|
||||
})
|
||||
|
||||
test.each(['light', 'dark'])('uses the alt prop in %s mode', async (mode) => {
|
||||
await page.evaluate((mode) => {
|
||||
document.documentElement.classList.toggle('dark', mode === 'dark')
|
||||
}, mode)
|
||||
|
||||
expect(
|
||||
await page.locator('.image-override img:visible').getAttribute('alt')
|
||||
).toBe('Override description')
|
||||
expect(
|
||||
await page.locator('.image-decorative img:visible').getAttribute('alt')
|
||||
).toBe('')
|
||||
expect(
|
||||
await page.locator('.image-fallback img:visible').getAttribute('alt')
|
||||
).toBe('Image description')
|
||||
})
|
||||
|
||||
test('updates both images when the alt prop changes', async () => {
|
||||
const descriptions = () =>
|
||||
page
|
||||
.locator('.image-override img')
|
||||
.evaluateAll((images) =>
|
||||
images.map((image) => image.getAttribute('alt'))
|
||||
)
|
||||
|
||||
await page.getByRole('button', { name: 'Update description' }).click()
|
||||
await expect
|
||||
.poll(descriptions)
|
||||
.toEqual(['Updated description', 'Updated description'])
|
||||
|
||||
await page.getByRole('button', { name: 'Clear description' }).click()
|
||||
await expect.poll(descriptions).toEqual(['', ''])
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,28 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { VPImage } from 'vitepress/theme'
|
||||
|
||||
const description = ref('Override description')
|
||||
const image = {
|
||||
light: '/pwa_light.svg',
|
||||
dark: '/pwa_dark.svg',
|
||||
alt: 'Image description'
|
||||
}
|
||||
</script>
|
||||
|
||||
# Themeable image descriptions
|
||||
|
||||
<div class="image-override">
|
||||
<VPImage :image :alt="description" />
|
||||
</div>
|
||||
|
||||
<div class="image-decorative">
|
||||
<VPImage :image alt="" />
|
||||
</div>
|
||||
|
||||
<div class="image-fallback">
|
||||
<VPImage :image />
|
||||
</div>
|
||||
|
||||
<button @click="description = 'Updated description'">Update description</button>
|
||||
<button @click="description = ''">Clear description</button>
|
||||
@ -0,0 +1,41 @@
|
||||
// @ts-expect-error the unit typecheck uses tsc; Vite compiles this SFC at runtime
|
||||
import VPImage from 'client/theme-default/components/VPImage.vue'
|
||||
import { createSSRApp } from 'vue'
|
||||
import { renderToString } from 'vue/server-renderer'
|
||||
|
||||
vi.mock('vitepress', () => ({ withBase: (path: string) => path }))
|
||||
|
||||
const images = [
|
||||
{ name: 'string', image: 'logo.svg', fallback: '', count: 1 },
|
||||
{
|
||||
name: 'single source',
|
||||
image: { src: 'logo.svg', alt: 'Image description' },
|
||||
fallback: 'Image description',
|
||||
count: 1
|
||||
},
|
||||
{
|
||||
name: 'themed sources',
|
||||
image: { light: 'light.svg', dark: 'dark.svg', alt: 'Image description' },
|
||||
fallback: 'Image description',
|
||||
count: 2
|
||||
},
|
||||
{
|
||||
name: 'themed sources without alt',
|
||||
image: { light: 'light.svg', dark: 'dark.svg' },
|
||||
fallback: '',
|
||||
count: 2
|
||||
}
|
||||
]
|
||||
|
||||
describe.each(images)('VPImage with $name', ({ image, fallback, count }) => {
|
||||
test.each(['Override description', '', undefined])(
|
||||
'respects the alt prop %j',
|
||||
async (alt) => {
|
||||
const html = await renderToString(createSSRApp(VPImage, { image, alt }))
|
||||
const descriptions = [...html.matchAll(/ alt(?:="([^"]*)")?/g)].map(
|
||||
([, value]) => value ?? ''
|
||||
)
|
||||
expect(descriptions).toEqual(Array(count).fill(alt ?? fallback))
|
||||
}
|
||||
)
|
||||
})
|
||||
Loading…
Reference in new issue