fix(test+web): 修复测试编译错误 + 前端构建问题

- 修复透析集成测试 TestApp.dialysis_state() 返回类型不匹配(39个错误)
- 修复 erp-core test_helpers SeaORM Database::connect API 变更
- 修复 health_alert/article/data 集成测试函数签名不匹配
- 修复 DailyMonitoringTab 缺失 Input import
- 修复 DeviceReadingsTab 未使用接口声明
- 修复 DialysisManageList keyword → search 参数名
This commit is contained in:
iven
2026-04-30 10:21:05 +08:00
parent 82cea6a108
commit d8735eb45c
8 changed files with 643 additions and 23 deletions

View File

@@ -0,0 +1,380 @@
import { useState, useCallback, useMemo } from 'react';
import { Table, Tag, Button, Modal, Form, InputNumber, DatePicker, Select, message, Popconfirm, Space, Input } from 'antd';
import { PlusOutlined, EditOutlined, DeleteOutlined, AuditOutlined } from '@ant-design/icons';
import { dayjs } from '../../utils/dayjs';
import type { Dayjs } from 'dayjs';
import { dialysisApi } from '../../api/health/dialysis';
import type { DialysisRecord } from '../../api/health/dialysis';
import { patientApi } from '../../api/health/patients';
import { usePaginatedData } from '../../hooks/usePaginatedData';
import { AuthButton } from '../../components/AuthButton';
import { handleApiError } from '../../api/client';
const DIALYSIS_TYPE_MAP: Record<string, { color: string; label: string }> = {
HD: { color: 'blue', label: 'HD' },
HDF: { color: 'green', label: 'HDF' },
HF: { color: 'purple', label: 'HF' },
};
const STATUS_MAP: Record<string, { color: string; label: string }> = {
pending: { color: 'orange', label: '待审核' },
reviewed: { color: 'green', label: '已审核' },
};
interface PatientOption {
id: string;
name: string;
}
export default function DialysisManageList() {
const [selectedPatientId, setSelectedPatientId] = useState<string | null>(null);
const [patientOptions, setPatientOptions] = useState<PatientOption[]>([]);
const [patientSearch, setPatientSearch] = useState('');
const [modalOpen, setModalOpen] = useState(false);
const [editingRecord, setEditingRecord] = useState<DialysisRecord | null>(null);
const [form] = Form.useForm();
const [submitting, setSubmitting] = useState(false);
const [reviewOpen, setReviewOpen] = useState(false);
const [reviewRecord, setReviewRecord] = useState<DialysisRecord | null>(null);
const [reviewSubmitting, setReviewSubmitting] = useState(false);
const searchPatients = async (keyword: string) => {
if (!keyword.trim()) {
setPatientOptions([]);
return;
}
try {
const res = await patientApi.list({ search: keyword, page: 1, page_size: 20 });
setPatientOptions(
(res.data || []).map((p) => ({ id: p.id, name: p.name })),
);
} catch {
// ignore
}
};
const fetcher = useCallback(
async (page: number, pageSize: number) => {
if (!selectedPatientId) return { data: [], total: 0, page: 1 };
return dialysisApi.listRecords(selectedPatientId, { page, page_size: pageSize });
},
[selectedPatientId],
);
const { data, total, page, loading, refresh } = usePaginatedData<DialysisRecord>(fetcher, 10);
const openCreateModal = () => {
if (!selectedPatientId) {
message.warning('请先选择患者');
return;
}
setEditingRecord(null);
form.resetFields();
form.setFieldsValue({ dialysis_type: 'HD' });
setModalOpen(true);
};
const openEditModal = (record: DialysisRecord) => {
setEditingRecord(record);
form.setFieldsValue({
dialysis_date: dayjs(record.dialysis_date),
start_time: record.start_time,
end_time: record.end_time,
dialysis_type: record.dialysis_type,
pre_weight: record.pre_weight,
post_weight: record.post_weight,
dry_weight: record.dry_weight,
pre_bp_systolic: record.pre_bp_systolic,
pre_bp_diastolic: record.pre_bp_diastolic,
post_bp_systolic: record.post_bp_systolic,
post_bp_diastolic: record.post_bp_diastolic,
pre_heart_rate: record.pre_heart_rate,
post_heart_rate: record.post_heart_rate,
ultrafiltration_volume: record.ultrafiltration_volume,
dialysis_duration: record.dialysis_duration,
blood_flow_rate: record.blood_flow_rate,
complication_notes: record.complication_notes,
});
setModalOpen(true);
};
const handleSubmit = async (values: Record<string, unknown>) => {
setSubmitting(true);
try {
const payload = {
...values,
patient_id: selectedPatientId!,
dialysis_date: (values.dialysis_date as Dayjs).format('YYYY-MM-DD'),
};
if (editingRecord) {
await dialysisApi.updateRecord(editingRecord.id, {
...payload,
version: editingRecord.version,
});
message.success('透析记录更新成功');
} else {
await dialysisApi.createRecord(payload as Parameters<typeof dialysisApi.createRecord>[0]);
message.success('透析记录添加成功');
}
setModalOpen(false);
setEditingRecord(null);
form.resetFields();
refresh();
} catch (err) {
handleApiError(err, editingRecord ? '更新失败' : '添加失败');
} finally {
setSubmitting(false);
}
};
const handleDelete = async (record: DialysisRecord) => {
try {
await dialysisApi.deleteRecord(record.id, record.version);
message.success('删除成功');
refresh();
} catch (err) {
handleApiError(err, '删除失败');
}
};
const handleReview = async () => {
if (!reviewRecord) return;
setReviewSubmitting(true);
try {
await dialysisApi.reviewRecord(reviewRecord.id, { version: reviewRecord.version });
message.success('审核完成');
setReviewOpen(false);
setReviewRecord(null);
refresh();
} catch (err) {
handleApiError(err, '审核失败');
} finally {
setReviewSubmitting(false);
}
};
const columns = useMemo(
() => [
{ title: '透析日期', dataIndex: 'dialysis_date', key: 'dialysis_date', width: 110 },
{
title: '类型',
dataIndex: 'dialysis_type',
key: 'dialysis_type',
width: 70,
render: (v: string) => {
const m = DIALYSIS_TYPE_MAP[v];
return m ? <Tag color={m.color}>{m.label}</Tag> : <Tag>{v}</Tag>;
},
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
width: 80,
render: (v: string) => {
const m = STATUS_MAP[v];
return m ? <Tag color={m.color}>{m.label}</Tag> : <Tag>{v}</Tag>;
},
},
{
title: '透前体重',
dataIndex: 'pre_weight',
key: 'pre_weight',
width: 90,
render: (v: number | null) => (v != null ? `${v} kg` : '-'),
},
{
title: '透后体重',
dataIndex: 'post_weight',
key: 'post_weight',
width: 90,
render: (v: number | null) => (v != null ? `${v} kg` : '-'),
},
{
title: '超滤量',
dataIndex: 'ultrafiltration_volume',
key: 'ultrafiltration_volume',
width: 80,
render: (v: number | null) => (v != null ? `${v} ml` : '-'),
},
{
title: '时长(分)',
dataIndex: 'dialysis_duration',
key: 'dialysis_duration',
width: 80,
render: (v: number | null) => v ?? '-',
},
{
title: '操作',
key: 'actions',
width: 200,
render: (_: unknown, record: DialysisRecord) => (
<AuthButton code="health.dialysis.manage">
<Space size={0}>
{record.status === 'pending' && (
<Button type="link" size="small" icon={<AuditOutlined />} onClick={() => { setReviewRecord(record); setReviewOpen(true); }}>
</Button>
)}
<Button type="link" size="small" icon={<EditOutlined />} onClick={() => openEditModal(record)}>
</Button>
<Popconfirm title="确认删除该记录?" onConfirm={() => handleDelete(record)} okText="确认" cancelText="取消">
<Button type="link" size="small" danger icon={<DeleteOutlined />}>
</Button>
</Popconfirm>
</Space>
</AuthButton>
),
},
],
[openEditModal, handleDelete],
);
return (
<div>
<div style={{ marginBottom: 16, display: 'flex', gap: 12, alignItems: 'center' }}>
<Select
showSearch
style={{ width: 280 }}
placeholder="搜索选择患者"
filterOption={false}
onSearch={(v) => {
setPatientSearch(v);
searchPatients(v);
}}
onChange={(v) => setSelectedPatientId(v)}
notFoundContent={patientSearch ? '未找到患者' : '输入姓名搜索'}
options={patientOptions.map((p) => ({ value: p.id, label: p.name }))}
value={selectedPatientId || undefined}
/>
<Button icon={<PlusOutlined />} onClick={openCreateModal} disabled={!selectedPatientId}>
</Button>
</div>
{selectedPatientId ? (
<Table
columns={columns}
dataSource={data}
rowKey="id"
loading={loading}
size="small"
pagination={{
current: page,
total,
pageSize: 10,
onChange: (p) => refresh(p),
showTotal: (t) => `${t}`,
style: { margin: 0 },
}}
/>
) : (
<div style={{ textAlign: 'center', padding: 60, color: '#999' }}>
</div>
)}
<Modal
title={editingRecord ? '编辑透析记录' : '添加透析记录'}
open={modalOpen}
onCancel={() => {
setModalOpen(false);
setEditingRecord(null);
}}
onOk={() => form.submit()}
confirmLoading={submitting}
destroyOnClose
width={640}
>
<Form form={form} layout="vertical" onFinish={handleSubmit}>
<Form.Item name="dialysis_date" label="透析日期" rules={[{ required: true, message: '请选择日期' }]}>
<DatePicker style={{ width: '100%' }} />
</Form.Item>
<div style={{ display: 'flex', gap: 16 }}>
<Form.Item name="dialysis_type" label="透析方式" style={{ flex: 1 }}>
<Select
options={[
{ value: 'HD', label: 'HD (血液透析)' },
{ value: 'HDF', label: 'HDF (血液透析滤过)' },
{ value: 'HF', label: 'HF (血液滤过)' },
]}
/>
</Form.Item>
<Form.Item name="dialysis_duration" label="时长(分钟)" style={{ flex: 1 }}>
<InputNumber min={0} max={600} style={{ width: '100%' }} />
</Form.Item>
</div>
<div style={{ display: 'flex', gap: 16 }}>
<Form.Item name="pre_weight" label="透前体重(kg)" style={{ flex: 1 }}>
<InputNumber min={0} max={300} step={0.1} style={{ width: '100%' }} />
</Form.Item>
<Form.Item name="post_weight" label="透后体重(kg)" style={{ flex: 1 }}>
<InputNumber min={0} max={300} step={0.1} style={{ width: '100%' }} />
</Form.Item>
<Form.Item name="dry_weight" label="干体重(kg)" style={{ flex: 1 }}>
<InputNumber min={0} max={300} step={0.1} style={{ width: '100%' }} />
</Form.Item>
</div>
<div style={{ display: 'flex', gap: 16 }}>
<Form.Item name="pre_bp_systolic" label="透前收缩压" style={{ flex: 1 }}>
<InputNumber min={0} max={300} placeholder="mmHg" style={{ width: '100%' }} />
</Form.Item>
<Form.Item name="pre_bp_diastolic" label="透前舒张压" style={{ flex: 1 }}>
<InputNumber min={0} max={200} placeholder="mmHg" style={{ width: '100%' }} />
</Form.Item>
</div>
<div style={{ display: 'flex', gap: 16 }}>
<Form.Item name="post_bp_systolic" label="透后收缩压" style={{ flex: 1 }}>
<InputNumber min={0} max={300} placeholder="mmHg" style={{ width: '100%' }} />
</Form.Item>
<Form.Item name="post_bp_diastolic" label="透后舒张压" style={{ flex: 1 }}>
<InputNumber min={0} max={200} placeholder="mmHg" style={{ width: '100%' }} />
</Form.Item>
</div>
<div style={{ display: 'flex', gap: 16 }}>
<Form.Item name="pre_heart_rate" label="透前心率" style={{ flex: 1 }}>
<InputNumber min={0} max={250} placeholder="bpm" style={{ width: '100%' }} />
</Form.Item>
<Form.Item name="post_heart_rate" label="透后心率" style={{ flex: 1 }}>
<InputNumber min={0} max={250} placeholder="bpm" style={{ width: '100%' }} />
</Form.Item>
</div>
<div style={{ display: 'flex', gap: 16 }}>
<Form.Item name="ultrafiltration_volume" label="超滤量(ml)" style={{ flex: 1 }}>
<InputNumber min={0} max={10000} style={{ width: '100%' }} />
</Form.Item>
<Form.Item name="blood_flow_rate" label="血流量(ml/min)" style={{ flex: 1 }}>
<InputNumber min={0} max={600} style={{ width: '100%' }} />
</Form.Item>
</div>
<Form.Item name="complication_notes" label="并发症备注">
<Input.TextArea rows={2} placeholder="可选" />
</Form.Item>
</Form>
</Modal>
<Modal
title="审核透析记录"
open={reviewOpen}
onCancel={() => {
setReviewOpen(false);
setReviewRecord(null);
}}
onOk={handleReview}
confirmLoading={reviewSubmitting}
width={400}
>
{reviewRecord && (
<div>
<p><strong></strong>{reviewRecord.dialysis_date}</p>
<p><strong></strong>{reviewRecord.dialysis_type}</p>
<p><strong></strong>{reviewRecord.dialysis_duration ?? '-'} </p>
<p></p>
</div>
)}
</Modal>
</div>
);
}

View File

@@ -0,0 +1,248 @@
import { useCallback, useState, useMemo } from 'react';
import { Table, Button, Modal, Form, Input, InputNumber, DatePicker, message, Popconfirm, Space } from 'antd';
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
import { dayjs } from '../../../utils/dayjs';
import type { Dayjs } from 'dayjs';
import { healthDataApi } from '../../../api/health/healthData';
import type { DailyMonitoring } from '../../../api/health/healthData';
import { usePaginatedData } from '../../../hooks/usePaginatedData';
import { AuthButton } from '../../../components/AuthButton';
import { handleApiError } from '../../../api/client';
interface Props {
patientId: string;
}
export function DailyMonitoringTab({ patientId }: Props) {
const [modalOpen, setModalOpen] = useState(false);
const [editingRecord, setEditingRecord] = useState<DailyMonitoring | null>(null);
const [form] = Form.useForm();
const [submitting, setSubmitting] = useState(false);
const fetcher = useCallback(
async (page: number, pageSize: number) => {
return healthDataApi.listDailyMonitoring(patientId, { page, page_size: pageSize });
},
[patientId],
);
const { data, total, page, loading, refresh } = usePaginatedData<DailyMonitoring>(fetcher, 10);
const openCreateModal = () => {
setEditingRecord(null);
form.resetFields();
setModalOpen(true);
};
const openEditModal = (record: DailyMonitoring) => {
setEditingRecord(record);
form.setFieldsValue({
record_date: dayjs(record.record_date),
morning_bp_systolic: record.morning_bp_systolic,
morning_bp_diastolic: record.morning_bp_diastolic,
evening_bp_systolic: record.evening_bp_systolic,
evening_bp_diastolic: record.evening_bp_diastolic,
weight: record.weight,
blood_sugar: record.blood_sugar,
fluid_intake: record.fluid_intake,
urine_output: record.urine_output,
notes: record.notes,
});
setModalOpen(true);
};
const handleSubmit = async (values: {
record_date: Dayjs;
morning_bp_systolic?: number;
morning_bp_diastolic?: number;
evening_bp_systolic?: number;
evening_bp_diastolic?: number;
weight?: number;
blood_sugar?: number;
fluid_intake?: number;
urine_output?: number;
notes?: string;
}) => {
setSubmitting(true);
try {
const payload = {
...values,
record_date: values.record_date.format('YYYY-MM-DD'),
};
if (editingRecord) {
await healthDataApi.updateDailyMonitoring(editingRecord.id, {
...payload,
version: editingRecord.version,
});
message.success('日常监测记录更新成功');
} else {
await healthDataApi.createDailyMonitoring({ ...payload, patient_id: patientId });
message.success('日常监测记录添加成功');
}
setModalOpen(false);
setEditingRecord(null);
form.resetFields();
refresh();
} catch (err) {
handleApiError(err, editingRecord ? '更新失败' : '添加失败');
} finally {
setSubmitting(false);
}
};
const handleDelete = async (record: DailyMonitoring) => {
try {
await healthDataApi.deleteDailyMonitoring(record.id, record.version);
message.success('删除成功');
refresh();
} catch (err) {
handleApiError(err, '删除失败');
}
};
const columns = useMemo(
() => [
{ title: '记录日期', dataIndex: 'record_date', key: 'record_date', width: 110 },
{
title: '晨起血压',
key: 'morning_bp',
width: 120,
render: (_: unknown, r: DailyMonitoring) =>
r.morning_bp_systolic != null ? `${r.morning_bp_systolic}/${r.morning_bp_diastolic}` : '-',
},
{
title: '晚间血压',
key: 'evening_bp',
width: 120,
render: (_: unknown, r: DailyMonitoring) =>
r.evening_bp_systolic != null ? `${r.evening_bp_systolic}/${r.evening_bp_diastolic}` : '-',
},
{
title: '体重(kg)',
dataIndex: 'weight',
key: 'weight',
width: 90,
render: (v: number | null) => v ?? '-',
},
{
title: '血糖(mmol/L)',
dataIndex: 'blood_sugar',
key: 'blood_sugar',
width: 110,
render: (v: number | null) => v ?? '-',
},
{
title: '入量(ml)',
dataIndex: 'fluid_intake',
key: 'fluid_intake',
width: 90,
render: (v: number | null) => v ?? '-',
},
{
title: '出量(ml)',
dataIndex: 'urine_output',
key: 'urine_output',
width: 90,
render: (v: number | null) => v ?? '-',
},
{
title: '操作',
key: 'actions',
width: 120,
render: (_: unknown, record: DailyMonitoring) => (
<AuthButton code="health.health-data.manage">
<Space size={0}>
<Button type="link" size="small" icon={<EditOutlined />} onClick={() => openEditModal(record)}>
</Button>
<Popconfirm title="确认删除该记录?" onConfirm={() => handleDelete(record)} okText="确认" cancelText="取消">
<Button type="link" size="small" danger icon={<DeleteOutlined />}>
</Button>
</Popconfirm>
</Space>
</AuthButton>
),
},
],
[openEditModal, handleDelete],
);
return (
<div>
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'flex-end' }}>
<Button icon={<PlusOutlined />} onClick={openCreateModal}>
</Button>
</div>
<Table
columns={columns}
dataSource={data}
rowKey="id"
loading={loading}
size="small"
pagination={{
current: page,
total,
pageSize: 10,
onChange: (p) => refresh(p),
showTotal: (t) => `${t}`,
style: { margin: 0 },
}}
/>
<Modal
title={editingRecord ? '编辑日常监测' : '添加日常监测'}
open={modalOpen}
onCancel={() => {
setModalOpen(false);
setEditingRecord(null);
}}
onOk={() => form.submit()}
confirmLoading={submitting}
destroyOnClose
width={560}
>
<Form form={form} layout="vertical" onFinish={handleSubmit}>
<Form.Item name="record_date" label="记录日期" rules={[{ required: true, message: '请选择日期' }]}>
<DatePicker style={{ width: '100%' }} />
</Form.Item>
<div style={{ display: 'flex', gap: 16 }}>
<Form.Item name="morning_bp_systolic" label="晨起收缩压" style={{ flex: 1 }}>
<InputNumber min={0} max={300} placeholder="mmHg" style={{ width: '100%' }} />
</Form.Item>
<Form.Item name="morning_bp_diastolic" label="晨起舒张压" style={{ flex: 1 }}>
<InputNumber min={0} max={200} placeholder="mmHg" style={{ width: '100%' }} />
</Form.Item>
</div>
<div style={{ display: 'flex', gap: 16 }}>
<Form.Item name="evening_bp_systolic" label="晚间收缩压" style={{ flex: 1 }}>
<InputNumber min={0} max={300} placeholder="mmHg" style={{ width: '100%' }} />
</Form.Item>
<Form.Item name="evening_bp_diastolic" label="晚间舒张压" style={{ flex: 1 }}>
<InputNumber min={0} max={200} placeholder="mmHg" style={{ width: '100%' }} />
</Form.Item>
</div>
<div style={{ display: 'flex', gap: 16 }}>
<Form.Item name="weight" label="体重(kg)" style={{ flex: 1 }}>
<InputNumber min={0} max={500} step={0.1} placeholder="kg" style={{ width: '100%' }} />
</Form.Item>
<Form.Item name="blood_sugar" label="血糖(mmol/L)" style={{ flex: 1 }}>
<InputNumber min={0} max={50} step={0.1} placeholder="mmol/L" style={{ width: '100%' }} />
</Form.Item>
</div>
<div style={{ display: 'flex', gap: 16 }}>
<Form.Item name="fluid_intake" label="入量(ml)" style={{ flex: 1 }}>
<InputNumber min={0} max={10000} placeholder="ml" style={{ width: '100%' }} />
</Form.Item>
<Form.Item name="urine_output" label="出量(ml)" style={{ flex: 1 }}>
<InputNumber min={0} max={10000} placeholder="ml" style={{ width: '100%' }} />
</Form.Item>
</div>
<Form.Item name="notes" label="备注">
<Input.TextArea rows={2} placeholder="可选备注" />
</Form.Item>
</Form>
</Modal>
</div>
);
}

View File

@@ -45,11 +45,6 @@ interface Props {
/* ---------- 原始数据 Tab ---------- */
interface RawFilters {
deviceType: string | undefined;
hours: number;
}
function RawDataTab({ patientId }: Props) {
const [deviceType, setDeviceType] = useState<string | undefined>(undefined);
const [hours, setHours] = useState<number>(24);
@@ -162,11 +157,6 @@ function RawDataTab({ patientId }: Props) {
/* ---------- 小时聚合 Tab ---------- */
interface HourlyFilters {
deviceType: string | undefined;
days: number;
}
function HourlyAggTab({ patientId }: Props) {
const [deviceType, setDeviceType] = useState<string | undefined>(undefined);
const [days, setDays] = useState<number>(7);

View File

@@ -3,7 +3,7 @@
//! 每个测试在独立事务中执行,测试结束自动回滚,无数据残留。
//! 多个测试共享同一个数据库连接池,无连接竞争。
use sea_orm::{ConnectOptions, DatabaseConnection, DatabaseTransaction};
use sea_orm::{ConnectOptions, Database, DatabaseConnection, DatabaseTransaction, TransactionTrait};
use std::sync::OnceLock;
use tokio::sync::OnceCell;
@@ -25,7 +25,7 @@ async fn db_pool() -> &'static DatabaseConnection {
let opt = ConnectOptions::new(db_url())
.max_connections(5)
.to_owned();
DatabaseConnection::connect(opt)
Database::connect(opt)
.await
.expect("测试数据库连接失败")
})

View File

@@ -249,7 +249,7 @@ async fn test_alert_list_filter_and_tenant_isolation() {
// 按患者 A 过滤
let (alerts_a, total_a) = alert_service::list_alerts(
app.health_state(), app.tenant_id(), Some(patient_a), None, 1, 20,
app.health_state(), app.tenant_id(), Some(patient_a), None, None, 1, 20,
)
.await
.unwrap();
@@ -259,7 +259,7 @@ async fn test_alert_list_filter_and_tenant_isolation() {
// 租户隔离
let other_tenant = uuid::Uuid::new_v4();
let (_alerts_other, total_other) = alert_service::list_alerts(
app.health_state(), other_tenant, Some(patient_a), None, 1, 20,
app.health_state(), other_tenant, Some(patient_a), None, None, 1, 20,
)
.await
.unwrap();

View File

@@ -236,7 +236,7 @@ async fn test_article_soft_delete() {
.expect("删除应成功");
let result = article_service::get_article(
app.health_state(), app.tenant_id(), article.id,
app.health_state(), app.tenant_id(), article.id, true,
)
.await;
assert!(result.is_err(), "软删除后查询应失败");
@@ -252,7 +252,7 @@ async fn test_article_tenant_isolation() {
let other_tenant = uuid::Uuid::new_v4();
let result = article_service::get_article(
app.health_state(), other_tenant, article.id,
app.health_state(), other_tenant, article.id, true,
)
.await;
assert!(result.is_err(), "不同租户不应看到此文章");

View File

@@ -3,7 +3,6 @@
//! 验证体征 CRUD、化验报告 CRUD + 审阅、租户隔离、乐观锁。
use erp_health::dto::health_data_dto::*;
use erp_dialysis::dto::dialysis_dto::ReviewLabReportReq;
use erp_health::service::health_data_service;
use super::test_fixture::TestApp;

View File

@@ -14,6 +14,7 @@ use super::test_db::TestDb;
pub struct TestApp {
test_db: TestDb,
health_state: HealthState,
dialysis_state: DialysisState,
tenant_id: uuid::Uuid,
operator_id: uuid::Uuid,
}
@@ -26,9 +27,15 @@ impl TestApp {
event_bus: EventBus::new(100),
crypto: PiiCrypto::dev_default(),
};
let dialysis_state = DialysisState {
db: test_db.db().clone(),
event_bus: health_state.event_bus.clone(),
crypto: health_state.crypto.clone(),
};
Self {
test_db,
health_state,
dialysis_state,
tenant_id: uuid::Uuid::new_v4(),
operator_id: uuid::Uuid::new_v4(),
}
@@ -42,12 +49,8 @@ impl TestApp {
&self.health_state
}
pub fn dialysis_state(&self) -> DialysisState {
DialysisState {
db: self.test_db.db().clone(),
event_bus: self.health_state.event_bus.clone(),
crypto: self.health_state.crypto.clone(),
}
pub fn dialysis_state(&self) -> &DialysisState {
&self.dialysis_state
}
pub fn tenant_id(&self) -> uuid::Uuid {