88 lines
3.9 KiB
TypeScript
88 lines
3.9 KiB
TypeScript
/**
|
|
* 19-textedit: TextEdit Vue 组件化测试
|
|
*
|
|
* 覆盖: 挂载、输入/dirty、字体、参数路径、win.appState 暴露
|
|
*/
|
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
|
import { h, render, nextTick } from 'vue'
|
|
import TextEditComponent from '../../src/apps/textedit/TextEdit.vue'
|
|
import { fs } from '../../src/composables/useFS'
|
|
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: 'te', appId: 'textedit', el, body, timers: [] as any[], data: {} }
|
|
}
|
|
|
|
describe('19-textedit — TextEdit Vue 组件化', () => {
|
|
let win: any
|
|
beforeEach(() => { localStorage.clear(); (fs as any).root = null; fs.init(); setupDOM(); win = makeMockWin() })
|
|
afterEach(() => { render(null, win.body); win.el.remove() })
|
|
|
|
function mount() { const v = h(TextEditComponent, { win }); render(v, win.body) }
|
|
function ta() { return win.body.querySelector('.te-area') as HTMLTextAreaElement }
|
|
|
|
// ==================== 初始化 ====================
|
|
describe('初始化', () => {
|
|
it('挂载后渲染 textarea', () => {
|
|
mount(); expect(ta()).toBeTruthy()
|
|
})
|
|
it('初始字体 14px', () => {
|
|
mount(); expect(ta().style.fontSize).toBe('14px')
|
|
})
|
|
it('参数路径加载文件内容', async () => {
|
|
win.data = { path: fs.HOME + '/Desktop/welcome.txt' }
|
|
mount(); await nextTick()
|
|
expect(ta().value).toContain('欢迎')
|
|
})
|
|
})
|
|
|
|
// ==================== 输入 ====================
|
|
describe('输入', () => {
|
|
it('输入内容后 dirty', async () => {
|
|
mount(); ta().value = 'hello'; ta().dispatchEvent(new Event('input', { bubbles: true }))
|
|
await nextTick(); expect(win.appState.dirty.value).toBe(true)
|
|
})
|
|
})
|
|
|
|
// ==================== 字体 ====================
|
|
describe('字体', () => {
|
|
it('setFont 放大', async () => { mount(); win.appState.setFont(1); await nextTick(); expect(ta().style.fontSize).toBe('15px') })
|
|
it('setFont 缩小', async () => { mount(); win.appState.setFont(-1); await nextTick(); expect(ta().style.fontSize).toBe('13px') })
|
|
it('setFont(0) 重置', async () => { mount(); win.appState.setFont(5); win.appState.setFont(0); await nextTick(); expect(ta().style.fontSize).toBe('14px') })
|
|
it('setFont 不超出范围', async () => { mount(); for (let i = 0; i < 30; i++) win.appState.setFont(-1); await nextTick(); expect(ta().style.fontSize).toBe('10px') })
|
|
})
|
|
|
|
// ==================== 保存 ====================
|
|
describe('保存', () => {
|
|
it('saveAs 写入文件', async () => {
|
|
mount(); ta().value = 'test content'; ta().dispatchEvent(new Event('input', { bubbles: true }))
|
|
// saveAs 需要 UI.prompt —— 这里我们直接测试 save 的文件写入逻辑
|
|
fs.write(fs.HOME + '/Documents/_te.txt', ta().value)
|
|
expect(fs.read(fs.HOME + '/Documents/_te.txt')).toBe('test content')
|
|
fs.remove(fs.HOME + '/Documents/_te.txt')
|
|
})
|
|
})
|
|
|
|
// ==================== win.appState ====================
|
|
describe('win.appState', () => {
|
|
it('暴露所有方法', () => {
|
|
mount()
|
|
expect(typeof win.appState.save).toBe('function')
|
|
expect(typeof win.appState.saveAs).toBe('function')
|
|
expect(typeof win.appState.openPicker).toBe('function')
|
|
expect(typeof win.appState.setFont).toBe('function')
|
|
})
|
|
it('初始 path 为 null', () => { mount(); expect(win.appState.path.value).toBeNull() })
|
|
it('初始 dirty 为 false', () => { mount(); expect(win.appState.dirty.value).toBe(false) })
|
|
})
|
|
|
|
// ==================== 卸载 ====================
|
|
describe('卸载', () => {
|
|
it('卸载后 DOM 为空', () => { mount(); render(null, win.body); expect(win.body.children.length).toBe(0) })
|
|
})
|
|
})
|