// // PunchPointModelsTests.swift // suixinkanTests // import CoreLocation import XCTest @testable import suixinkan /// 打卡点模型解码与格式化测试。 final class PunchPointModelsTests: XCTestCase { func testListItemDecodesRegionImagesQRCodeAndAuditFields() throws { let json = """ { "total": 1, "list": [{ "id": "9001", "name": "湖边平台", "status": 1, "status_label": "运营中", "region": {"lat": 30.1, "lot": 120.2, "address": "湖边", "scenic_spot_str": "景区湖边"}, "scenic_spot_str": "备用地址", "guide_imgs": ["https://cdn/1.jpg", "https://cdn/2.jpg"], "mp_qrcode": "https://cdn/qr.png", "created_at": "2026-07-08 10:00:00", "creator_id": "77", "creator": "张三", "creator_phone": "13800138000", "auditor": "李四", "audit_time": "2026-07-08 11:00:00", "audit_remark": "通过" }] } """.data(using: .utf8)! let response = try JSONDecoder().decode(PunchPointListResponse.self, from: json) XCTAssertEqual(response.total, 1) let item = try XCTUnwrap(response.list.first) XCTAssertEqual(item.id, 9001) XCTAssertEqual(item.statusLabel, "运营中") XCTAssertEqual(item.region?.lat, 30.1) XCTAssertEqual(item.region?.lot, 120.2) XCTAssertEqual(item.displayAddress, "湖边") XCTAssertEqual(item.guideImages.count, 2) XCTAssertEqual(item.mpQrcode, "https://cdn/qr.png") XCTAssertEqual(item.creatorId, 77) XCTAssertEqual(item.auditTime, "2026-07-08 11:00:00") XCTAssertEqual(PunchPointDisplayFormatter.maskedPhone(item.creatorPhone), "138****8000") } func testDetailDecodesDefaultsAndCoordinateFallbacks() throws { let json = """ { "id": 12, "name": "入口", "status": 3, "region": {"lat": 31.2, "lot": 121.3, "address": ""}, "scenic_spot_str": "景区入口", "description": "集合点" } """.data(using: .utf8)! let detail = try JSONDecoder().decode(PunchPointDetail.self, from: json) XCTAssertEqual(detail.statusLabel, "") XCTAssertEqual(detail.guideImages, []) XCTAssertNil(detail.mpQrcode) XCTAssertEqual(detail.displayAddress, "景区入口") XCTAssertEqual(detail.coordinate?.latitude, 31.2) XCTAssertEqual(detail.coordinate?.longitude, 121.3) XCTAssertEqual(detail.description, "集合点") XCTAssertEqual(PunchPointFilterType.rejected.apiStatus, 4) XCTAssertEqual(PunchPointFilterType.pendingReview.title, "未审核") } func testImageRemoteStateUsesURLAndUploadedFlag() { let image = PunchPointImageState.remote(url: "https://cdn.example.com/path/a.jpg") XCTAssertEqual(image.fileName, "a.jpg") XCTAssertEqual(image.previewURL, "https://cdn.example.com/path/a.jpg") XCTAssertEqual(image.uploadedURL, "https://cdn.example.com/path/a.jpg") XCTAssertTrue(image.isUploaded) XCTAssertFalse(image.isUploading) } func testOperatingAndAuditStatusPresentationMatchAndroid() { XCTAssertEqual(PunchPointDisplayFormatter.operatingStatus(1).title, "营运中") XCTAssertEqual(PunchPointDisplayFormatter.operatingStatus(2).title, "已暂停") XCTAssertEqual(PunchPointDisplayFormatter.operatingStatus(4).title, "未上线") XCTAssertEqual(PunchPointDisplayFormatter.auditStatus(1).title, "已通过") XCTAssertEqual(PunchPointDisplayFormatter.auditStatus(2).textColor, 0x22C55E) XCTAssertEqual(PunchPointDisplayFormatter.auditStatus(3).title, "待审核") XCTAssertEqual(PunchPointDisplayFormatter.auditStatus(4).title, "已驳回") } func testAllAndroidFiltersKeepExactStatusValuesAndTitles() { XCTAssertEqual(PunchPointFilterType.allCases.map(\.apiStatus), [0, 1, 2, 3, 4]) XCTAssertEqual( PunchPointFilterType.allCases.map(\.title), ["全部", "运营中", "已暂停", "未审核", "审核未通过"] ) } }