macos-web/tests/cases/25-quicktime.test.ts

85 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 25-quicktime: 深层测试——视频列表、导航、进度、音量、边界
*/
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
import { h, render, nextTick } from 'vue'
import QuickTimeComponent from '../../src/apps/quicktime/QuickTime.vue'
import { setupDOM } from '../helpers'
function makeMockWin() {
const el = document.createElement('div'); el.className = 'window'
document.getElementById('window-layer')?.appendChild(el)
const body = document.createElement('div'); body.className = 'win-body'
el.appendChild(body)
return { id: 'qt', appId: 'quicktime', el, body, timers: [] as any[], data: {} }
}
function click(win: any, selector: string) {
(win.body.querySelector(selector) as HTMLElement)?.dispatchEvent(new MouseEvent('click', { bubbles: true }))
}
describe('25-quicktime — 深层测试', () => {
let win: any
beforeEach(() => { setupDOM(); win = makeMockWin() })
afterEach(() => { render(null, win.body); win.el.remove() })
function mount() { const v = h(QuickTimeComponent, { win }); render(v, win.body) }
describe('结构', () => {
it('播放器完整结构', () => { mount(); expect(win.body.querySelector('.qt-stage')).toBeTruthy(); expect(win.body.querySelector('.qt-controls')).toBeTruthy() })
it('3 个控制按钮', () => { mount(); expect(win.body.querySelectorAll('.qt-btn').length).toBe(3) })
it('进度条和音量存在', () => { mount(); expect(win.body.querySelector('.qt-seek')).toBeTruthy(); expect(win.body.querySelector('.qt-vol')).toBeTruthy() })
it('时间显示初始值', () => { mount(); expect(win.body.querySelectorAll('.music-time').length).toBe(2) })
})
describe('导航', () => {
it('nav(1) 切换到下一个视频', async () => {
mount(); win.appState.nav(1); await nextTick()
// 第二个视频加载(花朵 → 星期五)
expect(win.body.querySelector('.qt-stage')).toBeTruthy()
})
it('nav(-1) 切换到上一个视频', async () => {
mount(); win.appState.nav(-1); await nextTick()
// 循环到最后一个(花朵 ← 大雄兔)
expect(win.body.querySelector('.qt-stage')).toBeTruthy()
})
it('连续 nav 循环', async () => {
mount()
for (let i = 0; i < 3; i++) { win.appState.nav(1); await nextTick() }
// 3 次后应回到第一个
expect(win.body.querySelector('.qt-stage')).toBeTruthy()
})
})
describe('控制', () => {
it('toggle 存在且可调用jsdom 无 video API验证不抛异常', () => {
mount()
expect(typeof win.appState.toggle).toBe('function')
try { win.appState.toggle() } catch { /* video API 缺失 */ }
})
it('播放按钮点击', () => { mount(); click(win, '.qt-btn'); expect(win.body.querySelector('.qt-btn')).toBeTruthy() })
it('进度条拖拽', () => {
mount()
const seek = win.body.querySelector('.qt-seek') as HTMLInputElement
seek.value = '50'; seek.dispatchEvent(new Event('input', { bubbles: true }))
expect(seek.value).toBe('50')
})
it('音量拖拽触发 onVol', () => {
mount()
const vol = win.body.querySelector('.qt-vol') as HTMLInputElement
vol.value = '30'; vol.dispatchEvent(new Event('input', { bubbles: true }))
expect(vol.value).toBe('30')
})
})
describe('appState', () => {
it('暴露 toggle/nav', () => {
mount()
expect(typeof win.appState.toggle).toBe('function')
expect(typeof win.appState.nav).toBe('function')
})
})
describe('卸载', () => {
it('卸载后 DOM 为空', () => { mount(); render(null, win.body); expect(win.body.children.length).toBe(0) })
})
})