```
feat: 添加拍药盒功能和语音直达入口 - 实现拍药盒扫描流程,支持本地OCR识别药品信息 - 在日记页面添加拍药盒和记症状的三选一入口 - 优化按钮点击区域,确保符合苹果HIG最小命中区标准 - 添加用药记录到时间线的独立分类显示 - 实现长按+号语音直达功能,支持语音意图分类跳转 - 更新项目配置文件,启用代码分析和死代码剥离选项 - 增加多项本地化字符串支持新功能 ```
This commit is contained in:
85
康康Tests/MedicationScanServiceTests.swift
Normal file
85
康康Tests/MedicationScanServiceTests.swift
Normal file
@@ -0,0 +1,85 @@
|
||||
import Testing
|
||||
import Foundation
|
||||
import SwiftData
|
||||
@testable import 康康
|
||||
|
||||
/// MedicationScanService.parseMedicationsJSON 纯函数单测(JSON 容错与去重)。
|
||||
struct MedicationScanServiceTests {
|
||||
|
||||
@Test func parsesStandardObject() throws {
|
||||
let raw = """
|
||||
{"medications":[{"name":"缬沙坦胶囊","strength":"80mg×7粒","usage":""}]}
|
||||
"""
|
||||
let meds = try MedicationScanService.parseMedicationsJSON(raw)
|
||||
#expect(meds.count == 1)
|
||||
#expect(meds[0].name == "缬沙坦胶囊")
|
||||
#expect(meds[0].strength == "80mg×7粒")
|
||||
#expect(meds[0].entryText == "缬沙坦胶囊 80mg×7粒")
|
||||
}
|
||||
|
||||
@Test func parsesBareArrayWithFence() throws {
|
||||
let raw = """
|
||||
```json
|
||||
[{"name":"二甲双胍缓释片","strength":"0.5g×30片","usage":"口服,一次1片,一日2次"}]
|
||||
```
|
||||
"""
|
||||
let meds = try MedicationScanService.parseMedicationsJSON(raw)
|
||||
#expect(meds.count == 1)
|
||||
#expect(meds[0].entryText == "二甲双胍缓释片 0.5g×30片 · 口服,一次1片,一日2次")
|
||||
}
|
||||
|
||||
@Test func parsesChineseKeysAndDedupes() throws {
|
||||
let raw = """
|
||||
{"medications":[
|
||||
{"药名":"阿司匹林肠溶片","规格":"100mg","用法":""},
|
||||
{"name":"阿司匹林肠溶片","strength":"100mg","usage":""}
|
||||
]}
|
||||
"""
|
||||
let meds = try MedicationScanService.parseMedicationsJSON(raw)
|
||||
#expect(meds.count == 1)
|
||||
}
|
||||
|
||||
@Test func emptyNameRowsAreDropped() throws {
|
||||
let raw = #"{"medications":[{"name":"","strength":"10mg","usage":""}]}"#
|
||||
let meds = try MedicationScanService.parseMedicationsJSON(raw)
|
||||
#expect(meds.isEmpty)
|
||||
}
|
||||
|
||||
@Test func trailingCommaIsRepaired() throws {
|
||||
let raw = #"{"medications":[{"name":"氯雷他定片","strength":"10mg×6片","usage":"",},]}"#
|
||||
let meds = try MedicationScanService.parseMedicationsJSON(raw)
|
||||
#expect(meds.count == 1)
|
||||
#expect(meds[0].name == "氯雷他定片")
|
||||
}
|
||||
|
||||
@Test func invalidJSONThrows() {
|
||||
#expect(throws: (any Error).self) {
|
||||
try MedicationScanService.parseMedicationsJSON("识别不出来,抱歉")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 「用药」日记 → 时间线分类映射(拍药盒入档落库后在「记录」tab 的归类)。
|
||||
@MainActor
|
||||
struct MedicationTimelineTests {
|
||||
|
||||
private func makeContext() throws -> ModelContext {
|
||||
let schema = Schema([DiaryEntry.self])
|
||||
let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
|
||||
return ModelContext(try ModelContainer(for: schema, configurations: [config]))
|
||||
}
|
||||
|
||||
@Test func medicationTaggedDiaryMapsToMedicationKind() throws {
|
||||
let ctx = try makeContext()
|
||||
let med = DiaryEntry(content: "缬沙坦胶囊 80mg×7粒", tags: [DiaryEntry.medicationTag])
|
||||
let plain = DiaryEntry(content: "今天睡得不错")
|
||||
ctx.insert(med); ctx.insert(plain)
|
||||
try ctx.save()
|
||||
|
||||
let medEntry = TimelineEntry.from(diary: med)
|
||||
#expect(medEntry.kind == .medication)
|
||||
#expect(medEntry.title == "缬沙坦胶囊 80mg×7粒")
|
||||
|
||||
#expect(TimelineEntry.from(diary: plain).kind == .diary)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user