Files
suixinkan_uikit/suixinkanTests/TaskAddViewModelTests.swift
汉秋 c083f1d4b3 升级 AppStore 缓存 Key 并在覆盖安装时强制重新登录。
统一账号作用域 Key 对齐 Android,新增缓存 schema 迁移清理旧数据,并同步更新相关模块与单元测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 09:35:55 +08:00

154 lines
6.1 KiB
Swift

//
// TaskAddViewModelTests.swift
// suixinkanTests
//
import XCTest
@testable import suixinkan
/// ViewModel
@MainActor
final class TaskAddViewModelTests: XCTestCase {
private var appStore: AppStore!
private var defaults: UserDefaults!
override func setUp() {
defaults = UserDefaults(suiteName: "TaskAddViewModelTests")!
defaults.removePersistentDomain(forName: "TaskAddViewModelTests")
appStore = AppStore(defaults: defaults)
appStore.session.configureTestAccount(scenicId: 10)
}
func testValidateRequiresTaskName() async {
let viewModel = TaskAddViewModel(appStore: appStore)
var message: String?
viewModel.onShowMessage = { message = $0 }
await viewModel.validateAndSubmit(api: TaskAPI(client: makeClient()))
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 testClearingCustomUrgentHourKeepsConfirmedValue() {
let viewModel = TaskAddViewModel(appStore: appStore)
viewModel.setUrgentHour(6)
viewModel.updateCustomUrgentHourText("")
XCTAssertEqual(viewModel.urgentHour, 6)
viewModel.updateCustomUrgentHourText("0")
XCTAssertEqual(viewModel.urgentHour, 6)
}
func testBuildAddTaskRequestSplitsCloudAndUploadFiles() {
let viewModel = TaskAddViewModel(appStore: appStore)
viewModel.updateTaskName("任务A")
viewModel.updateTaskDetails("描述")
viewModel.setSelectedOrderNumber("NO001")
viewModel.setUrgentHour(2)
viewModel.addCloudFiles([CloudFile(id: 1, name: "云文件", type: 2)])
viewModel.addUploadPlaceholder(fileName: "a.jpg", fileType: 2, uploadTaskId: "task1")
viewModel.markUploadSucceeded(uploadTaskId: "task1", fileURL: "https://cdn/a.jpg", autoRemarkWhenSingle: false)
let request = viewModel.buildAddTaskRequest()
XCTAssertEqual(request.name, "任务A")
XCTAssertEqual(request.orderNumber, "NO001")
XCTAssertEqual(request.urgentHour, 2)
XCTAssertEqual(request.cloudFile.count, 1)
XCTAssertEqual(request.uploadFile.count, 1)
XCTAssertEqual(request.uploadFile[0].fileUrl, "https://cdn/a.jpg")
}
func testPreparedUploadKeepsOriginalFileNameAndPreview() {
let viewModel = TaskAddViewModel(appStore: appStore)
let previewData = Data([1, 2, 3])
viewModel.addUploadPlaceholder(fileName: "temporary.jpg", fileType: 2, uploadTaskId: "task1")
viewModel.prepareUpload(uploadTaskId: "task1", fileName: "IMG_1001.HEIC", localPreviewData: previewData)
viewModel.markUploadSucceeded(
uploadTaskId: "task1",
fileURL: "https://cdn/image.heic",
fileName: "IMG_1001.HEIC",
localPreviewData: previewData,
autoRemarkWhenSingle: true
)
XCTAssertEqual(viewModel.selectedFiles[0].uploadFileName, "IMG_1001.HEIC")
XCTAssertEqual(viewModel.selectedFiles[0].localPreviewData, previewData)
XCTAssertEqual(viewModel.buildAddTaskRequest().uploadFile[0].fileName, "IMG_1001.HEIC")
XCTAssertEqual(viewModel.consumePendingRemarkFileID(), viewModel.selectedFiles[0].id)
}
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)])
XCTAssertEqual(viewModel.selectedFiles.count, 1)
XCTAssertEqual(viewModel.consumePendingRemarkFileID(), viewModel.selectedFiles[0].id)
viewModel.addCloudFiles([
CloudFile(id: 1, name: "A", type: 2),
CloudFile(id: 2, name: "B", type: 2),
CloudFile(id: 3, name: "C", type: 2),
])
XCTAssertEqual(viewModel.selectedFiles.count, 3)
XCTAssertNil(viewModel.consumePendingRemarkFileID())
}
func testResetAllStateClearsForm() {
let viewModel = TaskAddViewModel(appStore: appStore)
viewModel.updateTaskName("任务")
viewModel.setSelectedOrderNumber("NO001")
viewModel.addCloudFiles([CloudFile(id: 1, type: 2)])
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 {
APIClient(environment: .testing, session: MockURLSession(responses: []))
}
}