- Add useAppConfigStore (isCloud, isDevMode, tier, contractedClient, inferenceProfile) - Add GET /api/config/app endpoint to dev-api.py (reads env vars) - Replace flat /settings route with nested children (9 tabs) + redirect to my-profile - Add global router.beforeEach guard for system/fine-tune/developer tab access control - Add SettingsView.vue shell: desktop sidebar with group labels, mobile chip bar, RouterView - Tab visibility driven reactively by store state (cloud mode hides system, GPU profile gates fine-tune, devMode gates developer) - Tests: 3 store tests + 3 component tests, all passing
41 lines
1.2 KiB
TypeScript
41 lines
1.2 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
import { setActivePinia, createPinia } from 'pinia'
|
|
import { useAppConfigStore } from './appConfig'
|
|
|
|
vi.mock('../composables/useApi', () => ({
|
|
useApiFetch: vi.fn(),
|
|
}))
|
|
|
|
import { useApiFetch } from '../composables/useApi'
|
|
const mockFetch = vi.mocked(useApiFetch)
|
|
|
|
describe('useAppConfigStore', () => {
|
|
beforeEach(() => {
|
|
setActivePinia(createPinia())
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
it('defaults to safe values before load', () => {
|
|
const store = useAppConfigStore()
|
|
expect(store.isCloud).toBe(false)
|
|
expect(store.tier).toBe('free')
|
|
})
|
|
|
|
it('load() populates from API response', async () => {
|
|
mockFetch.mockResolvedValue({
|
|
data: { isCloud: true, isDevMode: false, tier: 'paid', contractedClient: false, inferenceProfile: 'cpu' },
|
|
error: null,
|
|
})
|
|
const store = useAppConfigStore()
|
|
await store.load()
|
|
expect(store.isCloud).toBe(true)
|
|
expect(store.tier).toBe('paid')
|
|
})
|
|
|
|
it('load() error leaves defaults intact', async () => {
|
|
mockFetch.mockResolvedValue({ data: null, error: { kind: 'network', message: 'fail' } })
|
|
const store = useAppConfigStore()
|
|
await store.load()
|
|
expect(store.isCloud).toBe(false)
|
|
})
|
|
})
|