Files
Aether/frontend/src/views/admin/__tests__/AdminOperationsDashboard.manual-refresh.spec.ts
T
elky 066ea87d72 feat: revamp analytics dashboards and harden database migrations
Add dashboard and overview analytics, health monitoring, provider expense tracking, and announcement updates across the gateway and frontend.

Keep schema migrations free of historical backfills while preserving automatic backfill execution. Bound migration deadlines, run schema preparation before Compose replacement, and anonymize deleted dashboard users.

Include the current documentation cleanup and regression coverage.
2026-10-01 11:48:17 +08:00

51 lines
2.9 KiB
TypeScript

import { createApp, defineComponent, h, nextTick, onMounted, onUnmounted } from 'vue'
import { createMemoryHistory, createRouter } from 'vue-router'
import { afterEach, describe, expect, it, vi } from 'vitest'
import AdminOperationsDashboard from '../AdminOperationsDashboard.vue'
vi.mock('@/features/overview/components/OverviewToolbar.vue', () => ({ default: { render: () => null } }))
const lifecycle = vi.hoisted(() => ({ mounted: [] as string[], unmounted: [] as string[] }))
function view(name: string) {
return defineComponent({
setup(_, { slots }) {
onMounted(() => lifecycle.mounted.push(name))
onUnmounted(() => lifecycle.unmounted.push(name))
return () => h('div', { 'data-view': name }, [name, slots.default?.({ snapshot: { node_id: 'live-node' } }), slots.details?.(), slots.diagnostics?.()])
},
})
}
vi.mock('@/features/overview/operations/RuntimeView.vue', () => ({ default: view('runtime') }))
vi.mock('@/features/overview/operations/PerformanceView.vue', () => ({ default: view('performance') }))
vi.mock('@/features/overview/operations/LiveMetrics.vue', () => ({ default: view('details') }))
vi.mock('@/features/overview/operations/RuntimeFocus.vue', () => ({ default: { render: () => null } }))
async function settle() { await Promise.resolve(); await Promise.resolve(); await nextTick(); await new Promise(resolve => setTimeout(resolve, 0)) }
describe('operations view lifecycle', () => {
afterEach(() => vi.useRealTimers())
it('keeps every section mounted regardless of legacy view query values or browser history', async () => {
lifecycle.mounted.length = 0
lifecycle.unmounted.length = 0
const router = createRouter({ history: createMemoryHistory(), routes: [{ path: '/admin/operations', component: AdminOperationsDashboard }] })
await router.push('/admin/operations?view=performance&from=2026-09-10T23:30:00Z&to=2026-09-11T00:30:00Z&timezone=UTC')
const root = document.createElement('div')
const app = createApp(AdminOperationsDashboard).use(router)
app.mount(root)
expect([...lifecycle.mounted].sort()).toEqual(['details', 'details', 'performance', 'runtime'])
expect(root.querySelector('[role="tablist"]')).toBeNull()
expect(root.querySelector('[role="tab"]')).toBeNull()
await router.push({ query: { ...router.currentRoute.value.query, view: 'resources' } })
await settle()
expect(lifecycle.mounted).toHaveLength(4)
expect(lifecycle.unmounted).toEqual([])
expect(router.currentRoute.value.query.from).toBe('2026-09-10T23:30:00Z')
router.back()
await settle()
for (const name of ['runtime', 'performance']) expect(root.querySelector(`[data-view="${name}"]`)).not.toBeNull()
expect(root.querySelectorAll('[data-view="details"]')).toHaveLength(2)
expect(lifecycle.unmounted).toEqual([])
app.unmount()
expect([...lifecycle.unmounted].sort()).toEqual(['details', 'details', 'performance', 'runtime'])
})
})