feat: 普通用户可维护应用版本号
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { mount, flushPromises } from '@vue/test-utils'
|
||||
import { ref } from 'vue'
|
||||
import ConfigView from '../views/ConfigView.vue'
|
||||
|
||||
global.fetch = vi.fn()
|
||||
@@ -23,6 +24,7 @@ function mockFetch(url) {
|
||||
'/api/config/servers': { '测试环境': { api: 'https://test.com', assDom: '', universalLink: '' } },
|
||||
'/api/config/branches': ['main', 'dev'],
|
||||
'/api/config/build': { max_concurrent_builds: 2, build_dir_retention_hours: 24, build_base_dir: '/tmp' },
|
||||
'/api/config/versions': { app_ver: '2.195.0', build_ver: '2.195.0.0' },
|
||||
'/api/config': { apps: {}, schemes: {}, branches: ['main'] },
|
||||
}
|
||||
return Promise.resolve({
|
||||
@@ -30,6 +32,17 @@ function mockFetch(url) {
|
||||
})
|
||||
}
|
||||
|
||||
const mountConfigView = ({ loggedIn = true, admin = true } = {}) => mount(ConfigView, {
|
||||
global: {
|
||||
provide: {
|
||||
showLogin: ref(false),
|
||||
getToken: () => '',
|
||||
isLoggedIn: ref(loggedIn),
|
||||
isAdmin: ref(admin),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
describe('ConfigView.vue', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
@@ -39,21 +52,19 @@ describe('ConfigView.vue', () => {
|
||||
})
|
||||
|
||||
it('未登录时显示权限提示', async () => {
|
||||
const wrapper = mount(ConfigView)
|
||||
const wrapper = mountConfigView({ loggedIn: false })
|
||||
await flushPromises()
|
||||
expect(wrapper.text()).toContain('需要管理员权限')
|
||||
expect(wrapper.text()).toContain('请先登录')
|
||||
})
|
||||
|
||||
it('已登录时显示管理页面', async () => {
|
||||
localStorageMock.getItem.mockReturnValue('true')
|
||||
const wrapper = mount(ConfigView)
|
||||
const wrapper = mountConfigView()
|
||||
await flushPromises()
|
||||
expect(wrapper.text()).toContain('配置管理')
|
||||
})
|
||||
|
||||
it('显示侧边栏菜单', async () => {
|
||||
localStorageMock.getItem.mockReturnValue('true')
|
||||
const wrapper = mount(ConfigView)
|
||||
const wrapper = mountConfigView()
|
||||
await flushPromises()
|
||||
|
||||
const menuItems = wrapper.findAll('.sidebar-menu li')
|
||||
@@ -65,16 +76,14 @@ describe('ConfigView.vue', () => {
|
||||
expect(texts).toContain('打包设置')
|
||||
})
|
||||
|
||||
it('默认显示服务器环境 tab', async () => {
|
||||
localStorageMock.getItem.mockReturnValue('true')
|
||||
const wrapper = mount(ConfigView)
|
||||
it('默认显示 Apps 配置 tab', async () => {
|
||||
const wrapper = mountConfigView()
|
||||
await flushPromises()
|
||||
expect(wrapper.text()).toContain('服务器环境配置')
|
||||
expect(wrapper.text()).toContain('Apps 配置')
|
||||
})
|
||||
|
||||
it('切换到分支管理 tab', async () => {
|
||||
localStorageMock.getItem.mockReturnValue('true')
|
||||
const wrapper = mount(ConfigView)
|
||||
const wrapper = mountConfigView()
|
||||
await flushPromises()
|
||||
|
||||
const branchesMenu = wrapper.findAll('.sidebar-menu li').find(li => li.text() === '分支管理')
|
||||
@@ -93,8 +102,7 @@ describe('ConfigView.vue', () => {
|
||||
return mockFetch(url)
|
||||
})
|
||||
|
||||
localStorageMock.getItem.mockReturnValue('true')
|
||||
const wrapper = mount(ConfigView)
|
||||
const wrapper = mountConfigView()
|
||||
await flushPromises()
|
||||
|
||||
const branchesMenu = wrapper.findAll('.sidebar-menu li').find(li => li.text() === '分支管理')
|
||||
@@ -122,8 +130,7 @@ describe('ConfigView.vue', () => {
|
||||
return mockFetch(url)
|
||||
})
|
||||
|
||||
localStorageMock.getItem.mockReturnValue('true')
|
||||
const wrapper = mount(ConfigView)
|
||||
const wrapper = mountConfigView()
|
||||
await flushPromises()
|
||||
|
||||
const branchesMenu = wrapper.findAll('.sidebar-menu li').find(li => li.text() === '分支管理')
|
||||
@@ -147,8 +154,7 @@ describe('ConfigView.vue', () => {
|
||||
})
|
||||
window.alert = vi.fn()
|
||||
|
||||
localStorageMock.getItem.mockReturnValue('true')
|
||||
const wrapper = mount(ConfigView)
|
||||
const wrapper = mountConfigView()
|
||||
await flushPromises()
|
||||
|
||||
const buildMenu = wrapper.findAll('.sidebar-menu li').find(li => li.text() === '打包设置')
|
||||
@@ -161,4 +167,20 @@ describe('ConfigView.vue', () => {
|
||||
|
||||
expect(window.alert).toHaveBeenCalledWith('设置已保存')
|
||||
})
|
||||
|
||||
it('普通账号可修改版本号但看不到打包参数', async () => {
|
||||
const wrapper = mountConfigView({ admin: false })
|
||||
await flushPromises()
|
||||
|
||||
const menuTexts = wrapper.findAll('.sidebar-menu li').map(li => li.text())
|
||||
expect(menuTexts).toEqual(['Apps 配置', '打包设置'])
|
||||
|
||||
const buildMenu = wrapper.findAll('.sidebar-menu li').find(li => li.text() === '打包设置')
|
||||
await buildMenu.trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.text()).toContain('应用版本号')
|
||||
expect(wrapper.text()).not.toContain('打包参数')
|
||||
expect(wrapper.findAll('input').length).toBe(2)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<li v-if="isAdmin" :class="{ active: tab === 'schemes' }" @click="tab = 'schemes'">Schemes 配置</li>
|
||||
<li v-if="isAdmin" :class="{ active: tab === 'branches' }" @click="tab = 'branches'">分支管理</li>
|
||||
<li v-if="isAdmin" :class="{ active: tab === 'upload' }" @click="tab = 'upload'">上传配置</li>
|
||||
<li v-if="isAdmin" :class="{ active: tab === 'build' }" @click="tab = 'build'">打包设置</li>
|
||||
<li :class="{ active: tab === 'build' }" @click="tab = 'build'">打包设置</li>
|
||||
<li v-if="isAdmin" :class="{ active: tab === 'json' }" @click="tab = 'json'">JSON 编辑</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -280,21 +280,23 @@
|
||||
</div>
|
||||
<button class="btn btn-primary" style="width: auto; padding: 10px 32px; margin-bottom: 24px;" @click="saveVersions">保存版本号</button>
|
||||
|
||||
<h4 class="section-title">打包参数</h4>
|
||||
<div class="form-group">
|
||||
<label>最大并行打包数</label>
|
||||
<input type="number" v-model.number="buildSettings.max_concurrent_builds" min="1" max="4">
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">建议 1-4,过高可能影响构建稳定性</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>打包目录保留时间(小时)</label>
|
||||
<input type="number" v-model.number="buildSettings.build_dir_retention_hours" min="1">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>打包基础目录</label>
|
||||
<input type="text" v-model="buildSettings.build_base_dir">
|
||||
</div>
|
||||
<button class="btn btn-primary" style="width: auto; padding: 10px 32px;" @click="saveBuildSettings">保存设置</button>
|
||||
<template v-if="isAdmin">
|
||||
<h4 class="section-title">打包参数</h4>
|
||||
<div class="form-group">
|
||||
<label>最大并行打包数</label>
|
||||
<input type="number" v-model.number="buildSettings.max_concurrent_builds" min="1" max="4">
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">建议 1-4,过高可能影响构建稳定性</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>打包目录保留时间(小时)</label>
|
||||
<input type="number" v-model.number="buildSettings.build_dir_retention_hours" min="1">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>打包基础目录</label>
|
||||
<input type="text" v-model="buildSettings.build_base_dir">
|
||||
</div>
|
||||
<button class="btn btn-primary" style="width: auto; padding: 10px 32px;" @click="saveBuildSettings">保存设置</button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -612,8 +614,12 @@ onMounted(async () => {
|
||||
|
||||
const loadData = async () => {
|
||||
if (!isAdmin.value) {
|
||||
const appsRes = await authFetch('/api/config/apps')
|
||||
const [appsRes, versionsRes] = await Promise.all([
|
||||
authFetch('/api/config/apps'),
|
||||
authFetch('/api/config/versions'),
|
||||
])
|
||||
if (appsRes.ok) apps.value = await appsRes.json()
|
||||
if (versionsRes.ok) versions.value = await versionsRes.json()
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user