Files
kangkang/康康Tests/CaptureServiceJSONTests.swift
link2026 77a4ee1c37 缺少代码差异信息,无法生成具体的commit message。请提供code differences内容以便分析并生成符合Angular规范的提交信息。
当您提供代码差异后,我将按照以下格式生成:

```
<type>(<scope>): <subject>

<body>
```

其中type会根据更改类型选择(feat、fix、docs、style、refactor等),scope表示影响范围,subject简要描述变更内容,body详细说明修改内容。
2026-06-07 14:17:18 +08:00

199 lines
8.8 KiB
Swift

import Testing
import Foundation
@testable import
struct CaptureServiceJSONTests {
@Test func parsesCleanJSON() throws {
let raw = """
{"title":"","type":"checkup","report_date":"2026-04-12","institution":"","page_count":2,"summary":"","indicators":[{"name":"LDL-C","value":"3.84","unit":"mmol/L","range":"< 3.40","status":"high"}]}
"""
let parsed = try CaptureService.parseReportJSON(raw)
#expect(parsed.title == "春检")
#expect(parsed.typeRaw == ReportType.checkup.rawValue)
#expect(parsed.institution == "协和")
#expect(parsed.pageCount == 2)
#expect(parsed.indicators.count == 1)
#expect(parsed.indicators.first?.status == .high)
}
@Test func stripsMarkdownCodeFence() throws {
let raw = """
```json
{"title":"x","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"","indicators":[]}
```
"""
let parsed = try CaptureService.parseReportJSON(raw)
#expect(parsed.title == "x")
#expect(parsed.typeRaw == ReportType.lab.rawValue)
#expect(parsed.indicators.isEmpty)
}
@Test func extractsObjectAfterLeadingText() throws {
let raw = """
好的,识别结果如下:
{"title":"y","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"","indicators":[]}
以上。
"""
let parsed = try CaptureService.parseReportJSON(raw)
#expect(parsed.title == "y")
}
@Test func handlesNestedBraces() throws {
let raw = """
{"title":"y","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"{x}","indicators":[]}
"""
let parsed = try CaptureService.parseReportJSON(raw)
#expect(parsed.summary == "含嵌套{x}对象")
}
@Test func handlesEscapedQuotesInStrings() throws {
let raw = #"{"title":"y \"内嵌\" 引号","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"","indicators":[]}"#
let parsed = try CaptureService.parseReportJSON(raw)
#expect(parsed.title == #"y "内嵌" "#)
}
@Test func fillsDefaultsForMissingFields() throws {
// 缺 title / type / report_date / institution / summary / page_count
let raw = """
{"indicators":[{"name":"X","value":"1","unit":"","range":"","status":"normal"}]}
"""
let parsed = try CaptureService.parseReportJSON(raw)
#expect(parsed.title == "") // 默认值
#expect(parsed.typeRaw == ReportType.other.rawValue)
#expect(parsed.indicators.count == 1)
}
@Test func skipsIndicatorsWithEmptyName() throws {
let raw = """
{"title":"t","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"","indicators":[
{"name":"","value":"1","unit":"","range":"","status":"normal"},
{"name":" ","value":"1","unit":"","range":"","status":"normal"},
{"name":"OK","value":"1","unit":"","range":"","status":"normal"}
]}
"""
let parsed = try CaptureService.parseReportJSON(raw)
#expect(parsed.indicators.count == 1)
#expect(parsed.indicators.first?.name == "OK")
}
@Test func malformedJSONThrows() {
let raw = " JSON"
#expect(throws: CaptureError.self) {
_ = try CaptureService.parseReportJSON(raw)
}
}
@Test func valueAsNumberStillParses() throws {
let raw = """
{"title":"t","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"","indicators":[{"name":"X","value":3.84,"unit":"","range":"","status":"high"}]}
"""
let parsed = try CaptureService.parseReportJSON(raw)
#expect(parsed.indicators.first?.value == "3.84")
}
@Test func unknownStatusFallsBackToNormal() throws {
let raw = """
{"title":"t","type":"lab","report_date":"2026-05-01","institution":"","page_count":1,"summary":"","indicators":[{"name":"X","value":"1","unit":"","range":"","status":"abnormal"}]}
"""
let parsed = try CaptureService.parseReportJSON(raw)
#expect(parsed.indicators.first?.status == .normal)
}
@Test func parsesRegionJSONWithChineseKeysAndArrowStatus() throws {
let raw = """
{"指标":[{"项目":"尿酸","结果":"486","单位":"μmol/L","参考范围":"208 - 428","异常":""}]}
"""
let indicators = try CaptureService.parseIndicatorsJSON(raw)
#expect(indicators.count == 1)
#expect(indicators.first?.name == "尿")
#expect(indicators.first?.value == "486")
#expect(indicators.first?.unit == "μmol/L")
#expect(indicators.first?.range == "208 - 428")
#expect(indicators.first?.status == .high)
}
@Test func parsesReportJSONWithChineseIndicatorArrayKey() throws {
let raw = """
{"title":"t","type":"lab","report_date":"2026-05-01","指标":[{"项目":"尿酸","结果":"486","单位":"μmol/L","参考范围":"208 - 428","异常":"偏高"}]}
"""
let parsed = try CaptureService.parseReportJSON(raw)
#expect(parsed.indicators.count == 1)
#expect(parsed.indicators.first?.name == "尿")
#expect(parsed.indicators.first?.status == .high)
}
@Test func parsesIndicatorEvidenceLocation() throws {
let raw = """
{"title":"t","type":"lab","report_date":"2026-05-01","page_count":2,"indicators":[{"name":"尿酸","value":"486","unit":"μmol/L","range":"208 - 428","status":"high","source_page":2,"source_box":[0.18,0.42,0.68,0.49]}]}
"""
let parsed = try CaptureService.parseReportJSON(raw, pageCount: 2)
let indicator = try #require(parsed.indicators.first)
#expect(indicator.sourcePageIndex == 1)
#expect(indicator.sourceBoxX == 0.18)
#expect(indicator.sourceBoxY == 0.42)
#expect(indicator.sourceBoxWidth == 0.68)
#expect(indicator.sourceBoxHeight == 0.49)
}
@Test func ignoresInvalidIndicatorEvidenceLocation() throws {
let raw = """
{"indicators":[{"name":"尿酸","value":"486","unit":"μmol/L","range":"208 - 428","status":"high","source_page":0,"source_box":[-1,0.42,0.68,1.5]}]}
"""
let parsed = try CaptureService.parseReportJSON(raw)
let indicator = try #require(parsed.indicators.first)
#expect(indicator.sourcePageIndex == nil)
#expect(indicator.sourceBoxX == nil)
#expect(indicator.sourceBoxY == nil)
#expect(indicator.sourceBoxWidth == nil)
#expect(indicator.sourceBoxHeight == nil)
}
@Test func infersStatusFromValueAndReferenceRangeWhenStatusMissing() throws {
let raw = """
{"indicators":[
{"name":"低密度脂蛋白","value":"3.84","unit":"mmol/L","range":"< 3.40"},
{"name":"白细胞","value":"2.8","unit":"10^9/L","range":"3.5 - 9.5"}
]}
"""
let indicators = try CaptureService.parseIndicatorsJSON(raw)
#expect(indicators.count == 2)
#expect(indicators[0].status == .high)
#expect(indicators[1].status == .low)
}
@Test func badReportDateFallsBackToNow() throws {
let raw = """
{"title":"t","type":"lab","report_date":"昨天","institution":"","page_count":1,"summary":"","indicators":[]}
"""
let parsed = try CaptureService.parseReportJSON(raw)
let now = Date()
let diff = abs(parsed.reportDate.timeIntervalSince(now))
#expect(diff < 5) // 5 秒内算 .now
}
/// VL 多项时偶尔直接吐裸数组 [{...},{...}],旧实现(只认 {})会只截第一项静默丢其余。
@Test func parsesTopLevelArrayAsIndicators() throws {
let raw = """
[{"name":"A","value":"1","unit":"","range":"","status":"high"},
{"name":"B","value":"2","unit":"","range":"","status":"low"}]
"""
let parsed = try CaptureService.parseReportJSON(raw)
#expect(parsed.indicators.count == 2)
#expect(parsed.indicators.first?.name == "A")
#expect(parsed.indicators.last?.status == .low)
}
/// VL 不同来源会吐 yyyy/MM/dd 等格式,不应回退到「今天」导致归档年份错位。
@Test func parsesSlashAndCJKDateFormats() throws {
for ds in ["2026/04/12", "2026.04.12", "20260412"] {
let raw = """
{"title":"t","type":"lab","report_date":"\(ds)","institution":"","page_count":1,"summary":"","indicators":[]}
"""
let parsed = try CaptureService.parseReportJSON(raw)
let c = Calendar(identifier: .gregorian).dateComponents([.year, .month, .day], from: parsed.reportDate)
#expect(c.year == 2026 && c.month == 4 && c.day == 12, " \(ds) ")
}
}
}