import { expect, test } from './fixtures.js' async function setup(page, core) { await page.goto(`/test/player.html?core=${core}&chapter=published`) await page.evaluate(() => window.createPlayer('/test/pattern.mp4')) await expect.poll(() => page.evaluate(() => window.art.isReady)).toBe(true) } for (const core of ['published', 'candidate']) { test(`${core}: sizing methods remain detachable own properties and ratio parsing retains legacy coercion`, async ({ page }) => { await setup(page, core) expect(await page.evaluate(() => { const art = window.art const descriptors = ['autoSize', 'autoHeight', 'aspectRatio', 'flip'].map((name) => { const descriptor = Object.getOwnPropertyDescriptor(art, name) return { name, configurable: descriptor.configurable, enumerable: descriptor.enumerable, writable: descriptor.writable ?? null } }) const { autoSize, autoHeight } = art const returns = [typeof Reflect.apply(autoSize, null, []), typeof Reflect.apply(autoHeight, {}, [])] art.template.$player.style.cssText = 'width:640px;height:360px;' const events = [] art.on('aspectRatio', value => events.push(value)) art.aspectRatio = ' 4 : 3 : ignored' const parsed = { value: art.aspectRatio, width: art.template.$video.style.width, height: art.template.$video.style.height } art.aspectRatio = '' art.aspectRatio = 'default' art.flip = 'custom' const custom = art.flip art.flip = '' const result = { descriptors, returns, parsed, events, custom, reset: art.flip } art.destroy() return result })).toEqual({ descriptors: ['autoSize', 'autoHeight', 'aspectRatio', 'flip'].map(name => ({ name, configurable: false, enumerable: false, writable: name.startsWith('auto') ? false : null })), returns: ['undefined', 'undefined'], parsed: { value: ' 4 : 3 : ignored', width: '480px', height: '100%' }, events: [' 4 : 3 : ignored', 'default', 'default'], custom: 'custom', reset: 'normal', }) }) } test('candidate: hidden containers defer sizing and recover after becoming visible', async ({ page }) => { await setup(page, 'candidate') expect(await page.evaluate(() => { const art = window.art const { $container, $video, $player } = art.template Object.defineProperties($video, { videoWidth: { configurable: true, value: 1920 }, videoHeight: { configurable: true, value: 1080 } }) $container.style.cssText = 'display:none;width:640px;height:480px;' $player.style.cssText = 'width:80%;height:70%;' const events = [] art.on('autoSize', value => events.push(['size', value])) art.on('autoHeight', value => events.push(['height', value])) art.autoSize() art.autoHeight() const hidden = { width: $player.style.width, height: $player.style.height, containerHeight: $container.style.height, count: events.length } $container.style.display = 'block' art.autoSize() art.autoHeight() const result = { hidden, events, height: $container.style.height } art.destroy() return result })).toEqual({ hidden: { width: '80%', height: '70%', containerHeight: '480px', count: 0 }, events: [['size', { width: 640, height: 360 }], ['height', 360]], height: '360px' }) }) test('candidate: malformed ratios preserve layout while retaining notices, datasets and events', async ({ page }) => { await setup(page, 'candidate') expect(await page.evaluate(() => { const art = window.art const { $video } = art.template art.aspectRatio = '4:3' const before = $video.getAttribute('style') const values = [] art.on('aspectRatio', value => values.push(value)) const stable = ['bad', '0:0', '-1:2', '1:0', 'Infinity:2'].map((value) => { art.aspectRatio = value return $video.getAttribute('style') === before && art.aspectRatio === value && art.template.$notice.textContent.includes(value) }) art.destroy() return { stable, values } })).toEqual({ stable: [true, true, true, true, true], values: ['bad', '0:0', '-1:2', '1:0', 'Infinity:2'] }) }) test('candidate: retained display setters and sizing methods do not write or emit after destroy', async ({ page }) => { await setup(page, 'candidate') expect(await page.evaluate(() => { const art = window.art const { $container, $player, $video } = art.template art.destroy(false) const before = [$container.outerHTML, $player.outerHTML, $video.outerHTML] const events = [] for (const name of ['autoSize', 'autoHeight', 'aspectRatio', 'flip']) art.on(name, () => events.push(name)) art.autoSize() art.autoHeight() art.aspectRatio = '4:3' art.flip = 'horizontal' return { same: before.every((html, index) => html === [$container, $player, $video][index].outerHTML), events } })).toEqual({ same: true, events: [] }) }) for (const core of ['published', 'candidate']) { test(`${core}: sizing preserves valid geometry, return values and emitted measurements`, async ({ page }) => { await setup(page, core) expect(await page.evaluate(() => { const art = window.art const { $container, $player, $video } = art.template Object.defineProperties($video, { videoWidth: { configurable: true, value: 1920 }, videoHeight: { configurable: true, value: 1080 } }) $container.style.cssText = 'width:640px;height:480px;' const sizes = [] const heights = [] art.on('autoSize', value => sizes.push(value)) art.on('autoHeight', value => heights.push(value)) const autoSize = art.autoSize() const styles = { width: $player.style.width, height: $player.style.height } const autoHeight = art.autoHeight() const result = { styles, sizes, heights, returns: [typeof autoSize, typeof autoHeight], containerHeight: $container.style.height } art.destroy() return result })).toEqual({ styles: { width: '100%', height: '75%' }, sizes: [{ width: 640, height: 360 }], heights: [360], returns: ['undefined', 'undefined'], containerHeight: '360px' }) }) test(`${core}: aspect ratio and flip preserve dataset, notices and event order`, async ({ page }) => { await setup(page, core) expect(await page.evaluate(() => { const art = window.art const events = [] art.on('aspectRatio', value => events.push(['aspectRatio', value])) art.on('flip', value => events.push(['flip', value])) art.aspectRatio = '4:3' const video = art.template.$video const ratio = { width: video.style.width, height: video.style.height, margin: video.style.margin, value: art.aspectRatio } art.flip = 'horizontal' const flip = art.flip art.aspectRatio = 'default' art.flip = 'normal' const result = { ratio, flip, reset: { width: video.style.width, height: video.style.height, margin: video.style.margin, ratio: art.aspectRatio, flip: art.flip }, events } art.destroy() return result })).toEqual({ ratio: { width: '480px', height: '100%', margin: '0px auto', value: '4:3' }, flip: 'horizontal', reset: { width: '', height: '', margin: '', ratio: 'default', flip: 'normal' }, events: [['aspectRatio', '4:3'], ['flip', 'horizontal'], ['aspectRatio', 'default'], ['flip', 'normal']] }) }) test(`${core}: unresolved media dimensions do not partially change layout or emit NaN height`, async ({ page }) => { await setup(page, core) expect(await page.evaluate(() => { const art = window.art const { $video, $player } = art.template Object.defineProperties($video, { videoWidth: { configurable: true, value: 0 }, videoHeight: { configurable: true, value: 0 } }) $player.style.width = '80%' $player.style.height = '70%' const events = [] art.on('autoHeight', value => events.push(Number.isFinite(value))) art.autoSize() art.autoHeight() const result = { width: $player.style.width, height: $player.style.height, finiteHeightEvents: events } art.destroy() return result })).toEqual({ width: core === 'candidate' ? '80%' : '100%', height: '70%', finiteHeightEvents: core === 'candidate' ? [] : [false] }) }) }