// // WildPhotographerReportTests.swift // suixinkanTests // // Created by Codex on 2026/7/1. // import XCTest @testable import suixinkan /// 举报摄影师模块测试,覆盖 Mock 数据、提交校验和列表筛选。 @MainActor final class WildPhotographerReportHomeViewModelTests: XCTestCase { /// 测试种子数据包含风险点和举报记录。 func testSeedDataLoadsReportsAndRiskPoints() { let viewModel = WildPhotographerReportHomeViewModel() XCTAssertFalse(viewModel.reports.isEmpty) XCTAssertFalse(viewModel.riskPoints.isEmpty) XCTAssertEqual(viewModel.reports.count, WildPhotographerReportMockStore.seedReports.count) } /// 测试提交后生成 JB 前缀编号并插入列表首位。 func testSubmitReportGeneratesDynamicID() { let viewModel = WildPhotographerReportHomeViewModel() let beforeCount = viewModel.reports.count let record = viewModel.submitReport( reportType: .suspectedWild, description: "测试举报说明", location: "测试景区 · 测试点位", contact: "13800138000", imageCount: 1, videoCount: 0 ) XCTAssertEqual(viewModel.reports.count, beforeCount + 1) XCTAssertEqual(viewModel.reports.first?.id, record.id) XCTAssertTrue(record.id.hasPrefix("JB")) XCTAssertEqual(record.status, .pending) XCTAssertEqual(record.reportType, .suspectedWild) XCTAssertEqual(record.phoneNumber, "13800138000") } } @MainActor final class WildPhotographerReportSubmitViewModelTests: XCTestCase { /// 测试无证据时提交会被拦截。 func testSubmitFailsWithoutEvidence() { let homeViewModel = WildPhotographerReportHomeViewModel() let viewModel = WildPhotographerReportSubmitViewModel(homeViewModel: homeViewModel) viewModel.images = [] viewModel.videos = [] viewModel.description = "有说明" viewModel.reportLocation = "测试位置" viewModel.locationConfirmed = true viewModel.submitReport() XCTAssertEqual(viewModel.validationMessage, "请至少上传一项现场证据。") XCTAssertNil(viewModel.submitResult) } /// 测试无说明时提交会被拦截。 func testSubmitFailsWithoutDescription() { let homeViewModel = WildPhotographerReportHomeViewModel() let viewModel = WildPhotographerReportSubmitViewModel(homeViewModel: homeViewModel) viewModel.description = " " viewModel.reportLocation = "测试位置" viewModel.locationConfirmed = true viewModel.submitReport() XCTAssertEqual(viewModel.validationMessage, "请填写举报说明。") XCTAssertNil(viewModel.submitResult) } /// 测试定位未确认时提交会被拦截。 func testSubmitFailsWithoutConfirmedLocation() { let homeViewModel = WildPhotographerReportHomeViewModel() let viewModel = WildPhotographerReportSubmitViewModel(homeViewModel: homeViewModel) viewModel.description = "测试说明" viewModel.locationConfirmed = false viewModel.submitReport() XCTAssertEqual(viewModel.validationMessage, "请先更新举报位置后再提交举报。") XCTAssertNil(viewModel.submitResult) } /// 测试定位更新中时提交会被拦截。 func testSubmitFailsWhileUpdatingLocation() { let homeViewModel = WildPhotographerReportHomeViewModel() let viewModel = WildPhotographerReportSubmitViewModel(homeViewModel: homeViewModel) viewModel.description = "测试说明" viewModel.isUpdatingLocation = true viewModel.locationConfirmed = true viewModel.reportLocation = "测试位置" viewModel.submitReport() XCTAssertEqual(viewModel.validationMessage, "正在获取定位,请稍后再提交。") XCTAssertNil(viewModel.submitResult) } /// 测试校验通过后会写入共享 Mock 列表。 func testSubmitSuccessCreatesRecord() { let homeViewModel = WildPhotographerReportHomeViewModel() let viewModel = WildPhotographerReportSubmitViewModel(homeViewModel: homeViewModel) viewModel.description = "测试说明" viewModel.reportLocation = "测试景区 · 测试点" viewModel.locationConfirmed = true viewModel.submitReport() XCTAssertNil(viewModel.validationMessage) XCTAssertNotNil(viewModel.submitResult) XCTAssertEqual(homeViewModel.reports.first?.id, viewModel.submitResult?.record.id) } } @MainActor final class WildPhotographerReportListViewModelTests: XCTestCase { /// 测试列表筛选只返回对应状态记录。 func testFilterReturnsMatchingStatus() { let homeViewModel = WildPhotographerReportHomeViewModel() let viewModel = WildPhotographerReportListViewModel(homeViewModel: homeViewModel) viewModel.selectFilter(.pending) XCTAssertTrue(viewModel.filteredReports.allSatisfy { $0.status == .pending }) viewModel.selectFilter(.processing) XCTAssertTrue(viewModel.filteredReports.allSatisfy { $0.status == .processing }) viewModel.selectFilter(.processed) XCTAssertTrue(viewModel.filteredReports.allSatisfy { $0.status == .processed }) viewModel.selectFilter(.all) XCTAssertEqual(viewModel.filteredReports.count, homeViewModel.reports.count) } }