Initial commit: iOS Build Server
- FastAPI backend with build queue, WebSocket logs, task management - Vue 3 frontend with build/config/history views - Xcode project build automation with IPA export - Fix: initialize build_dir before try block to ensure cleanup on early failure
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { createRouter, createMemoryHistory } from 'vue-router'
|
||||
import App from '../App.vue'
|
||||
|
||||
global.fetch = vi.fn()
|
||||
|
||||
// Mock localStorage
|
||||
const localStorageMock = (() => {
|
||||
let store = {}
|
||||
return {
|
||||
getItem: vi.fn(k => store[k] || null),
|
||||
setItem: vi.fn((k, v) => { store[k] = v }),
|
||||
removeItem: vi.fn(k => { delete store[k] }),
|
||||
clear: vi.fn(() => { store = {} }),
|
||||
}
|
||||
})()
|
||||
Object.defineProperty(global, 'localStorage', { value: localStorageMock })
|
||||
|
||||
function createMockRouter() {
|
||||
return createRouter({
|
||||
history: createMemoryHistory(),
|
||||
routes: [{ path: '/', component: { template: '<div />' } }],
|
||||
})
|
||||
}
|
||||
|
||||
describe('App.vue', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
localStorageMock.getItem.mockImplementation(k => null)
|
||||
})
|
||||
|
||||
it('显示标题', async () => {
|
||||
const router = createMockRouter()
|
||||
const wrapper = mount(App, {
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
expect(wrapper.text()).toContain('iOS 自动打包服务')
|
||||
})
|
||||
|
||||
it('未登录时显示登录按钮', async () => {
|
||||
const router = createMockRouter()
|
||||
const wrapper = mount(App, {
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
expect(wrapper.find('.btn-login').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('已登录时显示退出按钮', async () => {
|
||||
localStorageMock.getItem.mockReturnValue('true')
|
||||
const router = createMockRouter()
|
||||
const wrapper = mount(App, {
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
expect(wrapper.find('.btn-logout').exists()).toBe(true)
|
||||
expect(wrapper.find('.btn-login').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('点击登录按钮弹出登录框', async () => {
|
||||
const router = createMockRouter()
|
||||
const wrapper = mount(App, {
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
await wrapper.find('.btn-login').trigger('click')
|
||||
expect(wrapper.find('.login-modal').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('登录成功后更新状态', async () => {
|
||||
fetch.mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: () => Promise.resolve({ token: 'admin-token', is_admin: true }),
|
||||
})
|
||||
|
||||
const router = createMockRouter()
|
||||
const wrapper = mount(App, {
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
|
||||
await wrapper.find('.btn-login').trigger('click')
|
||||
await wrapper.find('.login-modal input[type="text"]').setValue('admin')
|
||||
await wrapper.find('.login-modal input[type="password"]').setValue('admin123')
|
||||
await wrapper.find('.login-btn').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.find('.btn-logout').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('登录失败显示错误', async () => {
|
||||
fetch.mockResolvedValueOnce({ ok: false })
|
||||
window.alert = vi.fn()
|
||||
|
||||
const router = createMockRouter()
|
||||
const wrapper = mount(App, {
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
|
||||
await wrapper.find('.btn-login').trigger('click')
|
||||
await wrapper.find('.login-modal input[type="text"]').setValue('admin')
|
||||
await wrapper.find('.login-modal input[type="password"]').setValue('wrong')
|
||||
await wrapper.find('.login-btn').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(window.alert).toHaveBeenCalledWith('用户名或密码错误')
|
||||
})
|
||||
|
||||
it('点击退出清除登录状态', async () => {
|
||||
localStorageMock.getItem.mockReturnValue('true')
|
||||
const router = createMockRouter()
|
||||
const wrapper = mount(App, {
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
|
||||
await wrapper.find('.btn-logout').trigger('click')
|
||||
expect(wrapper.find('.btn-login').exists()).toBe(true)
|
||||
expect(localStorageMock.removeItem).toHaveBeenCalledWith('isAdmin')
|
||||
})
|
||||
|
||||
it('已登录时显示管理导航', async () => {
|
||||
localStorageMock.getItem.mockReturnValue('true')
|
||||
const router = createMockRouter()
|
||||
const wrapper = mount(App, {
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
const links = wrapper.findAll('.nav a')
|
||||
const texts = links.map(l => l.text())
|
||||
expect(texts).toContain('管理')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user