import { describe, it, expect } from 'vitest' import { mount } from '@vue/test-utils' import ManagedImage from './ManagedImage.vue' /** * A CDN URL whose UUID/extension triggers responsive variant resolution * (so a `` with `` renders by default). */ const ORIGINAL = 'https://files.duffcloudservices.com/kept/assets/hero/abc-123.jpg' describe('ManagedImage self-healing fallback', () => { it('renders a with for a CDN image by default', () => { const wrapper = mount(ManagedImage, { props: { pageSlug: 'home', imageKey: 'hero.image', fallbackSrc: ORIGINAL, fallbackAlt: 'Hero', context: 'hero', }, }) expect(wrapper.find('picture').exists()).toBe(true) expect(wrapper.find('source').exists()).toBe(true) // Default src points at a generated variant, not the original. expect(wrapper.find('img').attributes('src')).toContain('abc-123-md.webp') }) it('swaps to the original and removes when the variant errors', async () => { const wrapper = mount(ManagedImage, { props: { pageSlug: 'home', imageKey: 'hero.image', fallbackSrc: ORIGINAL, fallbackAlt: 'Hero', context: 'hero', }, }) // Sanity: starts as a with variant . expect(wrapper.find('picture').exists()).toBe(true) expect(wrapper.find('source').exists()).toBe(true) // The 404'd fit-variant fires `error`. await wrapper.find('img').trigger('error') // The / branch must drop out — a does NOT // re-resolve after a 404s, so the variant set has to be removed. expect(wrapper.find('picture').exists()).toBe(false) expect(wrapper.find('source').exists()).toBe(false) // A plain now renders the ORIGINAL url. const img = wrapper.find('img') expect(img.exists()).toBe(true) expect(img.attributes('src')).toBe(ORIGINAL) // The original is still exposed for the visual editor. expect(img.attributes('data-dcs-image-url')).toBe(ORIGINAL) }) it('renders a plain at the original when `original` is set (no variants)', () => { const wrapper = mount(ManagedImage, { props: { pageSlug: 'home', imageKey: 'hero.image', fallbackSrc: ORIGINAL, fallbackAlt: 'Hero', context: 'hero', original: true, }, }) expect(wrapper.find('picture').exists()).toBe(false) expect(wrapper.find('img').attributes('src')).toBe(ORIGINAL) }) }) describe('ManagedImage layout-shift (CLS) dimension hints', () => { it('emits width/height on the when explicit dimensions are provided', () => { const wrapper = mount(ManagedImage, { props: { pageSlug: 'home', imageKey: 'hero.image', fallbackSrc: ORIGINAL, fallbackAlt: 'Hero', context: 'hero', width: 1920, height: 1080, }, }) const img = wrapper.find('img') expect(img.attributes('width')).toBe('1920') expect(img.attributes('height')).toBe('1080') // Hero context also gets the LCP priority hint. expect(img.attributes('fetchpriority')).toBe('high') }) it('emits NO width/height when dimensions are unknown (never fabricated)', () => { const wrapper = mount(ManagedImage, { props: { pageSlug: 'home', imageKey: 'hero.image', fallbackSrc: ORIGINAL, fallbackAlt: 'Hero', context: 'hero', }, }) const img = wrapper.find('img') expect(img.attributes('width')).toBeUndefined() expect(img.attributes('height')).toBeUndefined() }) it('reads .src/.width/.height from a D1-A dot-suffix imageBase and targets the .src key for the VE', () => { const wrapper = mount(ManagedImage, { props: { pageSlug: 'home', imageBase: 'hero.image', fallbackSrc: ORIGINAL, fallbackAlt: 'Hero', context: 'hero', width: 1600, height: 900, }, }) const img = wrapper.find('img') // Dimensions flow through to the CLS hint. expect(img.attributes('width')).toBe('1600') expect(img.attributes('height')).toBe('900') // The VE stages replacements against the `.src` key. expect(img.attributes('data-dcs-image-key')).toBe('hero.image.src') expect(img.attributes('data-dcs-image-url')).toBe(ORIGINAL) // … and alt changes against the `.alt` key (C-207 item 7). expect(img.attributes('data-dcs-image-alt-key')).toBe('hero.image.alt') }) }) describe('ManagedImage managed alt key exposure (data-dcs-image-alt-key)', () => { it('exposes the legacy altKey so the VE can stage a persistable alt change', () => { const wrapper = mount(ManagedImage, { props: { pageSlug: 'home', imageKey: 'hero.image', altKey: 'hero.imageAlt', fallbackSrc: ORIGINAL, fallbackAlt: 'Hero', context: 'hero', }, }) expect(wrapper.find('img').attributes('data-dcs-image-alt-key')).toBe('hero.imageAlt') }) it('omits the attribute when the image has no managed alt key', () => { const wrapper = mount(ManagedImage, { props: { pageSlug: 'home', imageKey: 'hero.image', fallbackSrc: ORIGINAL, fallbackAlt: 'Hero', context: 'hero', }, }) // No alt key ⇒ the VE must not preview an alt change it cannot persist. expect(wrapper.find('img').attributes('data-dcs-image-alt-key')).toBeUndefined() }) })