iOSBuildServer/frontend/src/__tests__/App.test.js
2026-07-20 14:54:06 +09:00

140 lines
4.3 KiB
JavaScript

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 () => {
const router = createMockRouter()
const wrapper = mount(App, {
global: { plugins: [router] },
})
await wrapper.find('.btn-login').trigger('click')
expect(wrapper.find('.login-modal').text()).not.toContain('默认账号')
expect(wrapper.find('.login-modal').text()).not.toContain('admin123')
})
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('管理')
})
})