Files
vigilcare-clinical/vigilcare-dashboard/src/__tests__/SimulationControlView.test.js
T
voltsrage 80b009fd23
CI / backend (push) Successful in 8m52s
CI / frontend (push) Failing after 1m39s
feature: Self-Service Clinical Testing Sessions
2026-08-06 04:03:04 +08:00

169 lines
5.0 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, beforeEach, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import SimulationControlView from '@/views/SimulationControlView.vue'
const {
fetchScenarios,
fetchSessions,
fetchRuns,
fetchSimulationConfig,
fetchDataSummary,
startRun,
startSession,
stopRun,
purgeData,
} = vi.hoisted(() => ({
fetchScenarios: vi.fn(),
fetchSessions: vi.fn(),
fetchRuns: vi.fn(),
fetchSimulationConfig: vi.fn(),
fetchDataSummary: vi.fn(),
startRun: vi.fn(),
startSession: vi.fn(),
stopRun: vi.fn(),
purgeData: vi.fn(),
}))
vi.mock('@/api/simulation', () => ({
fetchScenarios,
fetchSessions,
fetchRuns,
fetchSimulationConfig,
fetchDataSummary,
startRun,
startSession,
stopRun,
purgeData,
fetchRun: vi.fn(),
}))
vi.mock('@/stores/ward', () => ({
useWardStore: () => ({ loadEncounters: vi.fn() }),
}))
vi.mock('@/stores/alerts', () => ({
useAlertStore: () => ({ loadGlobalAlerts: vi.fn() }),
}))
const scenarios = [
{
id: 'uti-sepsis-elderly-01',
name: 'UTI Sepsis Elderly',
description: 'Elderly patient with UTI progressing to sepsis.',
durationMinutes: 480,
tags: ['sepsis', 'uti'],
department: 'GeneralMedicine',
eventCount: 200,
},
{
id: 'stable-baseline-01',
name: 'Stable Baseline',
description: 'Control scenario.',
durationMinutes: 480,
tags: ['control', 'stable'],
department: 'Surgery',
eventCount: 312,
},
]
const sessions = [
{
id: 'session-a-orientation',
name: 'Session A — Quick orientation',
goal: 'Learn the interface.',
estimatedMinutes: 25,
defaultSpeed: 60,
scenarios: [
{ id: 'stable-baseline-01', name: 'Stable Baseline' },
{ id: 'uti-sepsis-elderly-01', name: 'UTI Sepsis Elderly' },
],
},
]
describe('SimulationControlView', () => {
beforeEach(() => {
vi.clearAllMocks()
setActivePinia(createPinia())
fetchScenarios.mockResolvedValue(scenarios)
fetchSessions.mockResolvedValue(sessions)
fetchRuns.mockResolvedValue([])
fetchDataSummary.mockResolvedValue({
simulatedPatients: 0,
encounters: 0,
observations: 0,
alerts: 0,
activeRuns: 0,
})
fetchSimulationConfig.mockResolvedValue({
enabled: true,
maxSpeed: 600,
maxConcurrentRuns: 2,
})
})
it('defaultsToSessionsTab', async () => {
const wrapper = mount(SimulationControlView)
await vi.waitFor(() => expect(wrapper.text()).toContain('Session A — Quick orientation'))
expect(wrapper.text()).toContain('Testing sessions')
expect(wrapper.text()).not.toContain('Scenario catalogue')
})
it('switchesToScenariosTab', async () => {
const wrapper = mount(SimulationControlView)
await vi.waitFor(() => expect(wrapper.text()).toContain('Session A'))
const scenariosTab = wrapper.findAll('button').find(b => b.text() === 'Scenarios')
await scenariosTab.trigger('click')
await vi.waitFor(() => expect(wrapper.text()).toContain('Scenario catalogue'))
expect(wrapper.text()).toContain('UTI Sepsis Elderly')
})
it('showsWallClockDurationForSelectedScenarioSpeed', async () => {
const wrapper = mount(SimulationControlView)
await vi.waitFor(() => expect(wrapper.text()).toContain('Session A'))
const scenariosTab = wrapper.findAll('button').find(b => b.text() === 'Scenarios')
await scenariosTab.trigger('click')
await vi.waitFor(() => expect(wrapper.text()).toContain('UTI Sepsis Elderly'))
// Default Fast (60×): 480 sim minutes → 8 wall-clock minutes
expect(wrapper.text()).toMatch(/8 minutes for selected scenario/)
const realTime = wrapper.findAll('button').find(b => b.text().includes('Real time'))
expect(realTime.text()).toMatch(/8 hours for selected scenario/)
const instant = wrapper.findAll('button').find(b => b.text().includes('Instant'))
expect(instant.text()).toMatch(/1 minute for selected scenario/)
})
it('filtersCatalogueByTag', async () => {
const wrapper = mount(SimulationControlView)
await vi.waitFor(() => expect(wrapper.text()).toContain('Session A'))
const scenariosTab = wrapper.findAll('button').find(b => b.text() === 'Scenarios')
await scenariosTab.trigger('click')
await vi.waitFor(() => expect(wrapper.text()).toContain('Stable Baseline'))
const sepsisChip = wrapper.findAll('button').find(b => b.text() === 'sepsis')
await sepsisChip.trigger('click')
expect(wrapper.text()).toContain('UTI Sepsis Elderly')
expect(wrapper.text()).not.toContain('Stable Baseline')
})
it('showsEmptyStateWhenCatalogueMissing', async () => {
fetchScenarios.mockResolvedValue([])
const wrapper = mount(SimulationControlView)
await vi.waitFor(() => expect(wrapper.text()).toContain('Session A'))
const scenariosTab = wrapper.findAll('button').find(b => b.text() === 'Scenarios')
await scenariosTab.trigger('click')
await vi.waitFor(() =>
expect(wrapper.text()).toContain('Simulation:ScenarioDirectory'),
)
})
})