128 lines
5.2 KiB
TypeScript
128 lines
5.2 KiB
TypeScript
/**
|
||
* 27-safari: 深层测试——起始页/内置页/离线页、导航历史、地址栏、搜索引擎
|
||
*/
|
||
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
||
import { h, render, nextTick } from 'vue'
|
||
import SafariComponent from '../../src/apps/safari/Safari.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: 'sf', appId: 'safari', el, body, timers: [] as any[], data: {} }
|
||
}
|
||
|
||
describe('27-safari — 深层测试', () => {
|
||
let win: any
|
||
beforeEach(() => { setupDOM(); win = makeMockWin() })
|
||
afterEach(() => { render(null, win.body); win.el.remove() })
|
||
function mount() { const v = h(SafariComponent, { win }); render(v, win.body) }
|
||
|
||
describe('结构', () => {
|
||
it('地址栏存在', () => { mount(); expect(win.body.querySelector('.sf-addr')).toBeTruthy() })
|
||
it('后退/前进/刷新按钮', () => {
|
||
mount()
|
||
expect(win.body.querySelector('.fb-btn[title="后退"]')).toBeTruthy()
|
||
expect(win.body.querySelector('.fb-btn[title="前进"]')).toBeTruthy()
|
||
expect(win.body.querySelector('.fb-btn[title="重新载入"]')).toBeTruthy()
|
||
})
|
||
it('初始后退/前进禁用', () => {
|
||
mount()
|
||
expect((win.body.querySelector('.fb-btn[title="后退"]') as HTMLButtonElement)?.disabled).toBe(true)
|
||
expect((win.body.querySelector('.fb-btn[title="前进"]') as HTMLButtonElement)?.disabled).toBe(true)
|
||
})
|
||
})
|
||
|
||
describe('起始页', () => {
|
||
it('默认显示起始页(380ms 后)', async () => {
|
||
mount(); await new Promise(r => setTimeout(r, 500))
|
||
expect(win.body.querySelector('.sf-start')).toBeTruthy()
|
||
expect(win.body.querySelector('.sf-fav-grid')).toBeTruthy()
|
||
})
|
||
it('起始页有 4 个收藏', async () => {
|
||
mount(); await new Promise(r => setTimeout(r, 500))
|
||
expect(win.body.querySelectorAll('.sf-fav').length).toBe(4)
|
||
})
|
||
})
|
||
|
||
describe('内置页', () => {
|
||
it('导航到 macos://weather 显示内置页', async () => {
|
||
win.data = { url: 'macos://weather' }
|
||
mount(); await new Promise(r => setTimeout(r, 500))
|
||
expect(win.body.querySelector('.sf-builtin')).toBeTruthy()
|
||
})
|
||
it('导航到 macos://news 显示内置页', async () => {
|
||
win.data = { url: 'macos://news' }
|
||
mount(); await new Promise(r => setTimeout(r, 500))
|
||
expect(win.body.querySelector('.sf-builtin')).toBeTruthy()
|
||
})
|
||
it('导航到 macos://baike 显示内置页', async () => {
|
||
win.data = { url: 'macos://baike' }
|
||
mount(); await new Promise(r => setTimeout(r, 500))
|
||
expect(win.body.querySelector('.sf-builtin')).toBeTruthy()
|
||
})
|
||
it('导航到 macos://github 显示内置页', async () => {
|
||
win.data = { url: 'macos://github' }
|
||
mount(); await new Promise(r => setTimeout(r, 500))
|
||
expect(win.body.querySelector('.sf-builtin')).toBeTruthy()
|
||
})
|
||
})
|
||
|
||
describe('离线页', () => {
|
||
it('HTTP URL 显示离线页', async () => {
|
||
win.data = { url: 'https://example.com' }
|
||
mount(); await new Promise(r => setTimeout(r, 500))
|
||
expect(win.body.querySelector('.sf-offline')).toBeTruthy()
|
||
})
|
||
it('搜索关键词显示离线页(Bing 跳转)', async () => {
|
||
win.data = { url: 'test search' }
|
||
mount(); await new Promise(r => setTimeout(r, 500))
|
||
expect(win.body.querySelector('.sf-offline')).toBeTruthy()
|
||
})
|
||
})
|
||
|
||
describe('导航历史', () => {
|
||
it('导航到内置页后后退可用', async () => {
|
||
win.data = { url: 'macos://weather' }
|
||
mount(); await new Promise(r => setTimeout(r, 500))
|
||
await new Promise(r => setTimeout(r, 500))
|
||
// 再导航到 news
|
||
const addr = win.body.querySelector('.sf-addr') as HTMLInputElement
|
||
if (addr) { addr.value = 'macos://news'; addr.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true })) }
|
||
await new Promise(r => setTimeout(r, 600))
|
||
// 后退应可用(有历史)
|
||
const backBtn = win.body.querySelector('.fb-btn[title="后退"]') as HTMLButtonElement
|
||
expect(backBtn).toBeTruthy()
|
||
})
|
||
})
|
||
|
||
describe('URL 自动补全', () => {
|
||
it('输入 example.com 自动补 https://', async () => {
|
||
mount(); await new Promise(r => setTimeout(r, 500))
|
||
const addr = win.body.querySelector('.sf-addr') as HTMLInputElement
|
||
if (addr) {
|
||
addr.value = 'example.com'
|
||
addr.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', keyCode: 13, bubbles: true, cancelable: true }))
|
||
await new Promise(r => setTimeout(r, 600))
|
||
// verify not crashed
|
||
expect(addr).toBeTruthy()
|
||
}
|
||
})
|
||
})
|
||
|
||
describe('appState', () => {
|
||
it('暴露 back/fwd/reload', () => {
|
||
mount()
|
||
expect(typeof win.appState.back).toBe('function')
|
||
expect(typeof win.appState.fwd).toBe('function')
|
||
expect(typeof win.appState.reload).toBe('function')
|
||
})
|
||
})
|
||
|
||
describe('卸载', () => {
|
||
it('卸载后 DOM 为空', () => { mount(); render(null, win.body); expect(win.body.children.length).toBe(0) })
|
||
})
|
||
})
|