// // CloudStoragePickForTaskViewModelTests.swift // suixinkanTests // import XCTest @testable import suixinkan @MainActor /// 任务云盘多选 ViewModel 测试。 final class CloudStoragePickForTaskViewModelTests: XCTestCase { func testHandleItemTapTogglesMediaSelection() async throws { let listJSON = try makeListJSON(files: [ makeFileJSON(id: 5, name: "图片", type: 2), ]) let api = makeAPI(responses: [listJSON, listJSON]) let viewModel = CloudStoragePickForTaskViewModel() await viewModel.refresh(api: api) let file = try XCTUnwrap(viewModel.files.first) await viewModel.handleItemTap(file, api: api) XCTAssertTrue(viewModel.isSelected(5)) await viewModel.handleItemTap(file, api: api) XCTAssertFalse(viewModel.isSelected(5)) } func testHandleItemTapShowsImportedMessage() async throws { let listJSON = try makeListJSON(files: [ makeFileJSON(id: 5, name: "图片", type: 2), ]) let api = makeAPI(responses: [listJSON]) let viewModel = CloudStoragePickForTaskViewModel(importedFileIDs: [5]) var message: String? viewModel.onShowMessage = { message = $0 } await viewModel.refresh(api: api) let file = try XCTUnwrap(viewModel.files.first) await viewModel.handleItemTap(file, api: api) XCTAssertEqual(message, "已选择") XCTAssertFalse(viewModel.isSelected(5)) } func testNavigateToFolderUpdatesPathStack() async throws { let rootJSON = try makeListJSON(files: [ makeFileJSON(id: 8, name: "文件夹", type: 99), ]) let childJSON = try makeListJSON(files: []) let api = makeAPI(responses: [rootJSON, childJSON]) let viewModel = CloudStoragePickForTaskViewModel() await viewModel.refresh(api: api) let folder = try XCTUnwrap(viewModel.files.first) await viewModel.handleItemTap(folder, api: api) XCTAssertEqual(viewModel.pathStack.map(\.id), [0, 8]) } func testSelectedFileListReturnsAllChosenFiles() async throws { let listJSON = try makeListJSON(files: [ makeFileJSON(id: 1, name: "A", type: 2), makeFileJSON(id: 2, name: "B", type: 2), ]) let api = makeAPI(responses: [listJSON, listJSON, listJSON]) let viewModel = CloudStoragePickForTaskViewModel() await viewModel.refresh(api: api) await viewModel.handleItemTap(viewModel.files[0], api: api) await viewModel.handleItemTap(viewModel.files[1], api: api) 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))) } private func makeListJSON(files: [[String: Any]]) throws -> Data { let listData = try JSONSerialization.data(withJSONObject: files) let listObject = try JSONSerialization.jsonObject(with: listData) let envelope: [String: Any] = [ "code": 100000, "msg": "success", "data": [ "total": files.count, "list": listObject, ], ] return try JSONSerialization.data(withJSONObject: envelope) } private func makeFileJSON(id: Int, name: String, type: Int) -> [String: Any] { [ "id": id, "parent_folder_id": 0, "file_url": "https://cdn/\(id).jpg", "cover_url": "", "updated_at": "", "name": name, "created_at": "", "child_num": 0, "type": type, "file_size": 100, ] } }