macos-web/tests/cases/47-tv.test.ts

55 lines
4.1 KiB
TypeScript

/**
* 47-tv: Apple TV — 深层测试
* 覆盖: DOM(2)+卡片(5)+播放器(5)+视频(3)+边界(3)+卸载
* ⚠️ video.play/load jsdom 不支持,验证 DOM 状态
*/
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
import { h, render, nextTick } from 'vue'
import TVComponent from '../../src/apps/tv/TV.vue'
import { setupDOM } from '../helpers'
describe('47-tv', () => {
let body: HTMLElement, el: HTMLElement, win: any
beforeEach(() => {
setupDOM(); el = document.createElement('div'); el.className = 'window'; document.body.appendChild(el)
body = document.createElement('div'); body.className = 'win-body'; el.appendChild(body)
win = { el, body, timers: [], data: {} };
(window as any).Sys = () => ({ registerMedia: () => {}, unregisterMedia: () => {} })
})
afterEach(() => { render(null, body); el.remove() })
function m() { render(h(TVComponent, { win }), body) }
function card(i: number) { return body.querySelectorAll('.tv-card')[i] as HTMLElement }
function player() { return body.querySelector('.tv-player') as HTMLElement }
// --- DOM ---
it('tv-body 容器', () => { m(); expect(body.querySelector('.tv-body')).toBeTruthy() })
it('标题"立即观看"', () => { m(); expect(body.querySelector('.store-h')?.textContent).toBe('立即观看') })
// --- 卡片 ---
it('3 个视频卡片', () => { m(); expect(body.querySelectorAll('.tv-card').length).toBe(3) })
it('卡片有海报 .tv-poster', () => { m(); expect(card(0).querySelector('.tv-poster')).toBeTruthy() })
it('卡片有标题', () => { m(); [0, 1, 2].forEach(i => expect(card(i).querySelector('.tv-name')?.textContent).toBeTruthy()) })
it('卡片有来源', () => { m(); [0, 1, 2].forEach(i => expect(card(i).querySelector('.tv-sub')?.textContent).toBeTruthy()) })
it('海报含 ▶ 播放图标', () => { m(); expect(card(0).querySelector('.tv-poster span')?.textContent).toBe('▶') })
// --- 播放器 ---
it('player 初始隐藏', () => { m(); expect(player().classList.contains('hidden')).toBe(true) })
it('点击卡片→player 显示', async () => { m(); card(0).dispatchEvent(new MouseEvent('click', { bubbles: true })); await nextTick(); expect(player().classList.contains('hidden')).toBe(false) })
it('player 标题对应卡片', async () => { m(); card(0).dispatchEvent(new MouseEvent('click', { bubbles: true })); await nextTick(); expect(body.querySelector('.tv-ptitle')?.textContent).toContain('花朵') })
it('切换卡片更新标题', async () => { m(); card(0).dispatchEvent(new MouseEvent('click', { bubbles: true })); await nextTick(); card(1).dispatchEvent(new MouseEvent('click', { bubbles: true })); await nextTick(); expect(body.querySelector('.tv-ptitle')?.textContent).toContain('星期五') })
it('player 含 video 元素', async () => { m(); card(0).dispatchEvent(new MouseEvent('click', { bubbles: true })); await nextTick(); expect(player().querySelector('video')).toBeTruthy() })
// --- 视频 ---
it('video 有 source', async () => { m(); card(0).dispatchEvent(new MouseEvent('click', { bubbles: true })); await nextTick(); expect(player().querySelector('source')).toBeTruthy() })
it('video autoplay', async () => { m(); card(0).dispatchEvent(new MouseEvent('click', { bubbles: true })); await nextTick(); expect(player().querySelector('video')?.autoplay).toBe(true) })
it('video controls', async () => { m(); card(0).dispatchEvent(new MouseEvent('click', { bubbles: true })); await nextTick(); expect(player().querySelector('video')?.controls).toBe(true) })
// --- 边界 ---
it('同一卡片重复点击不崩', async () => { m(); card(0).dispatchEvent(new MouseEvent('click', { bubbles: true })); await nextTick(); card(0).dispatchEvent(new MouseEvent('click', { bubbles: true })); await nextTick() })
it('所有卡片海报有 ▶', () => { m(); [0, 1, 2].forEach(i => expect(card(i).querySelector('.tv-poster span')?.textContent).toBe('▶')) })
it('tv-grid 网格容器', () => { m(); expect(body.querySelector('.tv-grid')).toBeTruthy() })
// --- 卸载 ---
it('卸载后 DOM 为空', () => { m(); render(null, body); expect(body.children.length).toBe(0) })
})