feature: Clinical Review Mode: Charts, Replay Controls & Alert Reasoning

This commit is contained in:
voltsrage
2026-06-20 14:17:58 +08:00
parent 2ca0078223
commit ebd53f2df6
19 changed files with 939 additions and 9 deletions
@@ -0,0 +1,46 @@
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import AlertReasoning from '@/components/alerts/AlertReasoning.vue'
const sepsisAlert = {
id: 'alert-1',
alertType: 'SepsisWarning',
severity: 'Critical',
details: 'SIRS criteria met',
triggeredAt: '2026-06-19T12:00:00Z',
}
const qsofaAlert = {
id: 'alert-2',
alertType: 'QsofaWarning',
severity: 'Warning',
details: 'qSOFA score elevated',
triggeredAt: '2026-06-19T12:30:00Z',
}
describe('AlertReasoning', () => {
it('showsExplanationForSepsisWarning', () => {
const wrapper = mount(AlertReasoning, { props: { alert: sepsisAlert } })
expect(wrapper.text()).toContain('SIRS / Sepsis Alert')
expect(wrapper.text()).toContain('≥2 of 4 SIRS criteria met')
})
it('showsExplanationForQsofa', () => {
const wrapper = mount(AlertReasoning, { props: { alert: qsofaAlert } })
expect(wrapper.text()).toContain('qSOFA Alert')
expect(wrapper.text()).toContain('≥2 of 3 qSOFA criteria met')
})
it('showsRawDetailsForUnknownType', () => {
const unknown = {
id: 'alert-3',
alertType: 'CustomUnknown',
severity: 'Warning',
details: 'Something unusual happened',
triggeredAt: '2026-06-19T13:00:00Z',
}
const wrapper = mount(AlertReasoning, { props: { alert: unknown } })
expect(wrapper.text()).toContain('CustomUnknown')
expect(wrapper.text()).toContain('Something unusual happened')
})
})
@@ -0,0 +1,42 @@
import { describe, it, expect } from 'vitest'
import { defineComponent } from 'vue'
import { mount } from '@vue/test-utils'
import { useChartData } from '@/composables/useChartData'
function mountChartData(observations, code) {
let exposed
const Comp = defineComponent({
setup() {
exposed = useChartData(observations, code)
return () => null
},
})
mount(Comp)
return exposed
}
const observations = [
{ observationCode: 'HEART_RATE', value: 80, recordedAt: '2026-06-19T12:00:00Z' },
{ observationCode: 'RESP_RATE', value: 18, recordedAt: '2026-06-19T12:00:00Z' },
{ observationCode: 'HEART_RATE', value: 72, recordedAt: '2026-06-19T11:00:00Z' },
]
describe('useChartData', () => {
it('filtersObservationsByCode', () => {
const { chartData } = mountChartData(observations, 'HEART_RATE')
expect(chartData.value.datasets[0].data).toEqual([72, 80])
expect(chartData.value.labels).toHaveLength(2)
})
it('sortsChronologically', () => {
const { chartData } = mountChartData(observations, 'HEART_RATE')
expect(chartData.value.datasets[0].data[0]).toBe(72)
expect(chartData.value.datasets[0].data[1]).toBe(80)
})
it('handlesEmptyData', () => {
const { chartData } = mountChartData([], 'HEART_RATE')
expect(chartData.value.labels).toEqual([])
expect(chartData.value.datasets[0].data).toEqual([])
})
})
@@ -0,0 +1,33 @@
import { describe, it, expect } from 'vitest'
import { useReplayControls } from '@/composables/useReplayControls'
describe('useReplayControls', () => {
it('pauseAndResume', () => {
const { isPaused, pause, resume } = useReplayControls()
expect(isPaused.value).toBe(false)
pause()
expect(isPaused.value).toBe(true)
resume()
expect(isPaused.value).toBe(false)
})
it('speedPresets', () => {
const { speed, setSpeed } = useReplayControls()
expect(speed.value).toBe(60)
setSpeed(360)
expect(speed.value).toBe(360)
})
it('progressComputation', () => {
const { currentOffsetMinutes, scenarioDurationMinutes, progress } = useReplayControls()
scenarioDurationMinutes.value = 100
currentOffsetMinutes.value = 50
expect(progress.value).toBe(50)
})
it('jumpToOffset', () => {
const { currentOffsetMinutes, jumpToOffset } = useReplayControls()
jumpToOffset(42)
expect(currentOffsetMinutes.value).toBe(42)
})
})