将会话、权限、位置、收款与排队存储拆分为独立模块,同步更新各 ViewModel 与单元测试,并补充素材管理 UI 与个人空间设置交互。 Co-authored-by: Cursor <cursoragent@cursor.com>
154 lines
6.1 KiB
Swift
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.currentScenicId = 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: []))
|
|
}
|
|
}
|