修复任务提交与弹窗交互问题

This commit is contained in:
2026-07-10 14:51:34 +08:00
parent df547a16dc
commit f88a85a807
48 changed files with 1065 additions and 254 deletions

View File

@ -73,6 +73,25 @@ final class CloudStoragePickForTaskViewModelTests: XCTestCase {
XCTAssertEqual(Set(viewModel.selectedFileList.map(\.id)), Set([1, 2]))
}
func testAllowedFileTypeRejectsMismatchedMedia() async throws {
let listJSON = try makeListJSON(files: [
makeFileJSON(id: 1, name: "视频", type: 1),
makeFileJSON(id: 2, name: "图片", type: 2),
])
let api = makeAPI(responses: [listJSON])
let viewModel = CloudStoragePickForTaskViewModel(allowedFileType: 2)
var message: String?
viewModel.onShowMessage = { message = $0 }
await viewModel.refresh(api: api)
await viewModel.handleItemTap(viewModel.files[0], api: api)
await viewModel.handleItemTap(viewModel.files[1], api: api)
XCTAssertEqual(message, "请选择图片素材")
XCTAssertFalse(viewModel.isSelected(1))
XCTAssertTrue(viewModel.isSelected(2))
}
private func makeAPI(responses: [Data]) -> TaskAPI {
TaskAPI(client: APIClient(environment: .testing, session: MockURLSession(responses: responses)))
}

View File

@ -118,6 +118,45 @@ final class MaterialManagementViewModelTests: XCTestCase {
XCTAssertNil(api.lastUploadRequest?.id)
}
func testCloudMediaImportBuildsMaterialRequestWithoutUploadingAgain() async {
let api = MockMaterialAPI()
api.spotResponse = ScenicSpotListResponse(list: [ScenicSpotItem(id: 9, name: "打卡点")], total: 1)
let viewModel = MaterialFormViewModel(mode: .create, currentScenicIdProvider: { 3 })
var didSucceed = false
viewModel.onSubmitSuccess = { didSucceed = true }
await viewModel.loadInitial(api: api)
viewModel.updateMaterialName("云盘素材")
viewModel.selectScenicSpot(ScenicSpotItem(id: 9, name: "打卡点"))
viewModel.addCloudMediaFiles([
CloudFile(id: 31, fileUrl: "https://cdn/cloud.jpg", coverUrl: "https://cdn/cover-thumb.jpg", name: "cloud.jpg", type: 2, fileSize: 88),
])
await viewModel.setCoverImage(makeUploadItem(fileName: "cover.jpg"), uploader: MockMaterialUploader(urls: ["https://cdn/cover.jpg"]))
await viewModel.submit(api: api)
XCTAssertTrue(didSucceed)
XCTAssertEqual(viewModel.importedCloudFileIDs, Set([31]))
XCTAssertEqual(api.lastUploadRequest?.mediaList.first?.originalName, "cloud.jpg")
XCTAssertEqual(api.lastUploadRequest?.mediaList.first?.ossUrl, "https://cdn/cloud.jpg")
XCTAssertEqual(api.lastUploadRequest?.mediaList.first?.size, 88)
}
func testCloudMediaImportFiltersByCurrentMaterialTypeAndDeduplicates() {
let viewModel = MaterialFormViewModel(mode: .create, currentScenicIdProvider: { 3 })
var messages: [String] = []
viewModel.onShowMessage = { messages.append($0) }
viewModel.addCloudMediaFiles([
CloudFile(id: 1, fileUrl: "https://cdn/video.mp4", name: "video.mp4", type: 1),
CloudFile(id: 2, fileUrl: "https://cdn/image.jpg", name: "image.jpg", type: 2),
CloudFile(id: 2, fileUrl: "https://cdn/image.jpg", name: "image.jpg", type: 2),
])
XCTAssertEqual(viewModel.uploadedMediaList.map(\.ossUrl), ["https://cdn/image.jpg"])
XCTAssertEqual(viewModel.importedCloudFileIDs, Set([2]))
XCTAssertTrue(messages.isEmpty)
}
func testUploadDialogStaysHiddenAfterCompletionProgressCallback() async {
let viewModel = MaterialFormViewModel(mode: .create, currentScenicIdProvider: { 3 })
let uploader = MockMaterialUploader(urls: ["https://cdn/a.jpg"])

View File

@ -30,6 +30,32 @@ final class TaskAddViewModelTests: XCTestCase {
XCTAssertEqual(message, "请填写任务名称!")
}
func testTextInputsAreTrimmedToAndroidLimits() {
let viewModel = TaskAddViewModel(appStore: appStore)
viewModel.updateTaskName(String(repeating: "", count: 25))
viewModel.updateTaskDetails(String(repeating: "", count: 210))
viewModel.addCloudFiles([CloudFile(id: 1, name: "A", type: 2)])
viewModel.presentRemarkDialog(for: viewModel.selectedFiles[0].id)
viewModel.updateRemarkDialogText(String(repeating: "", count: 60))
XCTAssertEqual(viewModel.taskName.count, 20)
XCTAssertEqual(viewModel.taskDetails.count, 200)
XCTAssertEqual(viewModel.remarkDialogText.count, 50)
}
func testUploadingStateBlocksSubmitButKeepsButtonActionUseful() async {
let viewModel = TaskAddViewModel(appStore: appStore)
viewModel.updateTaskName("任务")
viewModel.addUploadPlaceholder(fileName: "a.jpg", fileType: 2, uploadTaskId: "task1")
var message: String?
viewModel.onShowMessage = { message = $0 }
await viewModel.validateAndSubmit(api: TaskAPI(client: makeClient()))
XCTAssertEqual(message, "文件正在上传中,请稍后添加!")
}
func testBuildAddTaskRequestSplitsCloudAndUploadFiles() {
let viewModel = TaskAddViewModel(appStore: appStore)
viewModel.updateTaskName("任务A")
@ -50,6 +76,14 @@ final class TaskAddViewModelTests: XCTestCase {
XCTAssertEqual(request.uploadFile[0].fileUrl, "https://cdn/a.jpg")
}
func testTaskFileSourceBadgeTextMatchesAndroidLabels() {
let cloudItem = TaskFileItem(source: .cloud, cloudFile: CloudFile(id: 1, name: "云文件", type: 2))
let uploadItem = TaskFileItem(source: .upload, uploadFileName: "a.jpg", uploadFileType: 2)
XCTAssertEqual(cloudItem.sourceBadgeText, "云盘")
XCTAssertEqual(uploadItem.sourceBadgeText, "本地")
}
func testAddCloudFilesDedupesAndAutoRemarkSingleFile() {
let viewModel = TaskAddViewModel(appStore: appStore)
viewModel.addCloudFiles([CloudFile(id: 1, name: "A", type: 2)])
@ -74,8 +108,12 @@ final class TaskAddViewModelTests: XCTestCase {
viewModel.resetAllState()
XCTAssertEqual(viewModel.taskName, "")
XCTAssertEqual(viewModel.taskDetails, "")
XCTAssertNil(viewModel.selectedOrderNumber)
XCTAssertEqual(viewModel.urgentHour, 0)
XCTAssertTrue(viewModel.selectedFiles.isEmpty)
XCTAssertFalse(viewModel.isUploading)
XCTAssertFalse(viewModel.showSuccessDialog)
}
private func makeClient() -> APIClient {

View File

@ -701,6 +701,20 @@ final class WildPhotographerReportTests: XCTestCase {
XCTAssertEqual(messages.last, URLError(.badServerResponse).localizedDescription)
}
func testSubmitLocationOmitsProvinceCityDistrict() {
let homeViewModel = WildPhotographerReportHomeViewModel()
let viewModel = WildPhotographerReportSubmitViewModel(homeViewModel: homeViewModel)
viewModel.applyResolvedLocation(HomeLocationSnapshot(
latitude: 32.40,
longitude: 119.41,
address: "江苏省扬州市邗江区瘦西湖路"
))
XCTAssertEqual(viewModel.locationTitleText, "当前定位:瘦西湖路")
XCTAssertEqual(viewModel.reportLocation, "瘦西湖路")
}
func testSubmitFailsWithoutEvidence() async {
let homeViewModel = WildPhotographerReportHomeViewModel()
let viewModel = WildPhotographerReportSubmitViewModel(homeViewModel: homeViewModel)
@ -766,7 +780,7 @@ final class WildPhotographerReportTests: XCTestCase {
viewModel.addImages([try makeAttachment(kind: .image, fileName: "scene.jpg")])
viewModel.addPaymentImages([try makeAttachment(kind: .payment, fileName: "payment.jpg")])
viewModel.updateDescription("测试说明")
viewModel.applyResolvedLocation(HomeLocationSnapshot(latitude: 30.12, longitude: 120.34, address: "测试景区 · 测试点"))
viewModel.applyResolvedLocation(HomeLocationSnapshot(latitude: 30.12, longitude: 120.34, address: "江苏省扬州市邗江区瘦西湖路"))
await viewModel.submitReport(api: api, uploader: uploader, scenicId: 9, scenicName: "测试景区")
@ -779,10 +793,13 @@ final class WildPhotographerReportTests: XCTestCase {
XCTAssertEqual(api.submitRequests.first?.reportType, 2)
XCTAssertEqual(api.submitRequests.first?.lat, 30.12)
XCTAssertEqual(api.submitRequests.first?.lng, 120.34)
XCTAssertEqual(api.submitRequests.first?.locationName, "测试景区")
XCTAssertEqual(api.submitRequests.first?.locationAddress, "瘦西湖路")
XCTAssertEqual(api.submitRequests.first?.evidences.count, 1)
XCTAssertEqual(api.submitRequests.first?.evidences.first?.fileType, 1)
XCTAssertEqual(api.submitRequests.first?.paymentScreenshots.count, 1)
XCTAssertNil(api.submitRequests.first?.storeUserId)
XCTAssertEqual(viewModel.submitResult?.record.location, "瘦西湖路")
}
func testPaymentScreenshotsDoNotReplaceRequiredEvidence() async throws {