iOSBuildServer/frontend/src/__tests__/HistoryView.test.js
2026-07-20 14:57:49 +09:00

192 lines
6.1 KiB
JavaScript
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.

import { describe, it, expect, vi, beforeEach } from 'vitest'
import { mount, flushPromises } from '@vue/test-utils'
import { createRouter, createMemoryHistory } from 'vue-router'
import HistoryView from '../views/HistoryView.vue'
global.fetch = vi.fn()
window.open = vi.fn()
const mockTasks = [
{ id: '1', app_name: 'App1', build_type: 'Ad_Hoc', scheme_name: 'readoor31OtherPayLongSchemeName', status: 'completed', created_at: '2024-01-01T10:00:00', dsym_path: '/path/dsym', oss_url: 'https://oss.com/app1.ipa', qr_code_path: '/path/qr.png' },
{ id: '2', app_name: 'App2', build_type: 'App_Store', scheme_name: 'sch2', status: 'failed', created_at: '2024-01-02T10:00:00', error_message: '构建失败', error_category: 'compilation' },
{ id: '3', app_name: 'App3', build_type: 'Ad_Hoc', scheme_name: 'sch1', status: 'pending', created_at: '2024-01-03T10:00:00' },
]
function createMockRouter() {
return createRouter({
history: createMemoryHistory(),
routes: [
{ path: '/', component: { template: '<div />' } },
{ path: '/build', component: { template: '<div />' } },
],
})
}
describe('HistoryView.vue', () => {
beforeEach(() => {
vi.clearAllMocks()
fetch.mockResolvedValue({
json: () => Promise.resolve(mockTasks),
})
})
it('显示打包历史标题', async () => {
const router = createMockRouter()
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises()
expect(wrapper.text()).toContain('打包历史')
})
it('加载并显示任务列表', async () => {
const router = createMockRouter()
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises()
const rows = wrapper.findAll('tbody tr')
expect(rows.length).toBe(3)
})
it('显示任务信息', async () => {
const router = createMockRouter()
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises()
expect(wrapper.text()).toContain('App1')
expect(wrapper.text()).toContain('App2')
expect(wrapper.text()).toContain('Ad_Hoc')
})
it('默认显示失败任务及完整失败原因', async () => {
const router = createMockRouter()
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises()
const rows = wrapper.findAll('tbody tr')
expect(rows.length).toBe(3)
expect(wrapper.text()).toContain('App1')
expect(wrapper.text()).toContain('App3')
expect(wrapper.text()).toContain('失败')
expect(wrapper.text()).toContain('编译错误')
expect(wrapper.text()).toContain('等待中')
})
it('按打包类型过滤', async () => {
const router = createMockRouter()
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises()
const selects = wrapper.findAll('.filter-select')
await selects[0].setValue('Ad_Hoc')
await wrapper.vm.$nextTick()
const rows = wrapper.findAll('tbody tr')
expect(rows.length).toBe(2) // App1 和 App3
})
it('按状态过滤', async () => {
const router = createMockRouter()
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises()
const selects = wrapper.findAll('.filter-select')
await selects[1].setValue('failed')
await wrapper.vm.$nextTick()
const rows = wrapper.findAll('tbody tr')
expect(rows.length).toBe(1) // App2
})
it('已完成任务显示下载按钮', async () => {
const router = createMockRouter()
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises()
// 第一行App1, completed应该有 dSYM 和下载按钮
const firstRow = wrapper.findAll('tbody tr')[0]
const buttons = firstRow.findAll('.action-btn')
const buttonTexts = buttons.map(b => b.text())
expect(buttonTexts).toContain('dSYM')
expect(buttonTexts).toContain('下载')
expect(buttonTexts).toContain('二维码')
})
it('空列表显示提示', async () => {
fetch.mockResolvedValue({ json: () => Promise.resolve([]) })
const router = createMockRouter()
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises()
expect(wrapper.text()).toContain('暂无打包记录')
})
it('状态文本正确', async () => {
const router = createMockRouter()
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises()
expect(wrapper.vm.statusText('pending')).toBe('等待中')
expect(wrapper.vm.statusText('running')).toBe('打包中')
expect(wrapper.vm.statusText('completed')).toBe('已完成')
expect(wrapper.vm.statusText('failed')).toBe('失败')
})
it('时间仅显示月和日Scheme 与状态单元格允许完整换行', async () => {
const router = createMockRouter()
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises()
expect(wrapper.vm.formatTime('2024-07-20T10:00:00')).toBe('7/20')
expect(wrapper.find('.scheme-cell').text()).toBe('readoor31OtherPayLongSchemeName')
expect(wrapper.find('.status-cell').text()).toContain('已完成')
})
it('点击查看日志跳转', async () => {
const router = createMockRouter()
router.push = vi.fn()
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises()
const logBtn = wrapper.findAll('.action-btn').find(b => b.text() === '日志')
await logBtn.trigger('click')
expect(router.push).toHaveBeenCalledWith({ path: '/build', query: { taskId: '1' } })
})
it('点击二维码弹出弹窗', async () => {
const router = createMockRouter()
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises()
const qrBtn = wrapper.findAll('.action-btn').find(b => b.text() === '二维码')
await qrBtn.trigger('click')
await wrapper.vm.$nextTick()
expect(wrapper.find('.qr-modal').exists()).toBe(true)
expect(wrapper.text()).toContain('下载二维码')
})
})