Files
suixinkan_ios_new/suixinkanTests/ScenicSettlement/ScenicSettlementViewModelTests.swift
汉秋 c39c3d3c75 新增订单长尾流程,并迁移排队、消息、结算与审核模块
将定金订单、历史拍摄与多行程上传接入 Orders,并以真实页面替换首页排队管理、消息中心、景区结算与提现审核占位入口。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-25 13:39:02 +08:00

213 lines
8.0 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// ScenicSettlementViewModelTests.swift
// suixinkanTests
//
// Created by Codex on 2026/6/25.
//
import XCTest
@testable import suixinkan
@MainActor
///
final class ScenicSettlementViewModelTests: XCTestCase {
///
func testSettlementLoadExcludesExistingScenics() async {
let permissionAPI = ScenicSettlementPermissionMock()
permissionAPI.scenicList = ScenicListAllResponse(total: 3, list: [
ScenicListItem(id: 1, name: "已有景区"),
ScenicListItem(id: 2, name: "新增景区"),
ScenicListItem(id: 3, name: "另一个景区")
])
let viewModel = ScenicSettlementViewModel()
await viewModel.load(
api: permissionAPI,
existingScenics: [BusinessScope(id: 1, name: "已有景区", kind: .scenic)]
)
XCTAssertEqual(viewModel.options.map(\.id), [2, 3])
}
/// 0
func testSettlementAmountValidation() {
let viewModel = ScenicSettlementViewModel()
XCTAssertEqual(viewModel.amountValidation, .empty)
viewModel.amountText = "0"
XCTAssertEqual(viewModel.amountValidation, .notPositive)
viewModel.amountText = "-1"
XCTAssertEqual(viewModel.amountValidation, .invalidFormat)
viewModel.amountText = "1.234"
XCTAssertEqual(viewModel.amountValidation, .invalidFormat)
viewModel.amountText = "12.30"
XCTAssertEqual(viewModel.amountValidation, .valid)
}
/// body
func testSettlementSubmitMultipleScenicsAndClearsForm() async {
let submitAPI = ScenicSettlementSubmitMock()
let viewModel = ScenicSettlementViewModel()
viewModel.options = [
ScenicSettlementOption(id: 3, name: "三号", selected: false),
ScenicSettlementOption(id: 2, name: "二号", selected: false)
]
viewModel.toggleScenic(id: 3)
viewModel.toggleScenic(id: 2)
viewModel.amountText = "99"
viewModel.remarkText = " 活动结算 "
let success = await viewModel.submit(api: submitAPI)
XCTAssertTrue(success)
XCTAssertEqual(submitAPI.requests, [
ScenicSettlementSubmitRequest(scenicId: 2, applyAmount: "99.00", applyRemark: "活动结算"),
ScenicSettlementSubmitRequest(scenicId: 3, applyAmount: "99.00", applyRemark: "活动结算")
])
XCTAssertTrue(viewModel.selectedScenicIds.isEmpty)
XCTAssertEqual(viewModel.amountText, "")
XCTAssertEqual(viewModel.remarkText, "")
XCTAssertEqual(viewModel.message, "提交成功,等待审核")
}
///
func testSettlementSubmitFailureKeepsForm() async {
let submitAPI = ScenicSettlementSubmitMock()
submitAPI.errorAfterRequestCount = 1
let viewModel = ScenicSettlementViewModel()
viewModel.options = [
ScenicSettlementOption(id: 1, name: "一号", selected: false),
ScenicSettlementOption(id: 2, name: "二号", selected: false)
]
viewModel.toggleScenic(id: 1)
viewModel.toggleScenic(id: 2)
viewModel.amountText = "10"
let success = await viewModel.submit(api: submitAPI)
XCTAssertFalse(success)
XCTAssertEqual(viewModel.selectedScenicIds, [1, 2])
XCTAssertEqual(viewModel.amountText, "10")
XCTAssertEqual(viewModel.message, TestError.sample.localizedDescription)
}
///
func testReviewLoadSuccessAggregatesRecords() async {
let permissionAPI = ScenicSettlementPermissionMock()
permissionAPI.scenicPendings = ScenicApplicationPendingsResponse(items: [
ScenicApplicationPendingResponse(id: 1, scenicName: "景区", status: 1)
])
permissionAPI.roleApplies = [
RoleApplyPendingResponse(id: 2, roleId: 1, roleName: "摄影师", status: 2)
]
let viewModel = ScenicSettlementReviewViewModel()
await viewModel.load(api: permissionAPI)
XCTAssertEqual(viewModel.scenicApplications.count, 1)
XCTAssertEqual(viewModel.roleApplications.count, 1)
XCTAssertEqual(viewModel.pendingCount, 1)
XCTAssertFalse(viewModel.loadFailedAll)
}
///
func testReviewSingleChannelFailureKeepsOtherChannel() async {
let permissionAPI = ScenicSettlementPermissionMock()
permissionAPI.scenicPendingsError = TestError.sample
permissionAPI.roleApplies = [
RoleApplyPendingResponse(id: 2, roleId: 1, roleName: "摄影师", status: 1)
]
let viewModel = ScenicSettlementReviewViewModel()
await viewModel.load(api: permissionAPI)
XCTAssertTrue(viewModel.scenicLoadFailed)
XCTAssertFalse(viewModel.roleLoadFailed)
XCTAssertFalse(viewModel.loadFailedAll)
XCTAssertEqual(viewModel.roleApplications.count, 1)
}
///
func testReviewBothChannelsFailureMarksFullFailure() async {
let permissionAPI = ScenicSettlementPermissionMock()
permissionAPI.scenicPendingsError = TestError.sample
permissionAPI.roleAppliesError = TestError.sample
let viewModel = ScenicSettlementReviewViewModel()
await viewModel.load(api: permissionAPI)
XCTAssertTrue(viewModel.loadFailedAll)
XCTAssertTrue(viewModel.scenicApplications.isEmpty)
XCTAssertTrue(viewModel.roleApplications.isEmpty)
}
///
func testReviewStatusMapping() {
let viewModel = ScenicSettlementReviewViewModel()
XCTAssertEqual(viewModel.statusText(1), "待审核")
XCTAssertEqual(viewModel.statusText(2), "已通过")
XCTAssertEqual(viewModel.statusText(3), "已驳回")
XCTAssertEqual(viewModel.statusText(9), "已取消")
XCTAssertEqual(viewModel.statusText(99), "未知")
XCTAssertEqual(viewModel.statusIcon(2), "checkmark.circle.fill")
}
}
@MainActor
private final class ScenicSettlementPermissionMock: ScenicPermissionServing {
var scenicList = ScenicListAllResponse(total: 0, list: [])
var scenicListError: Error?
var scenicPendings = ScenicApplicationPendingsResponse()
var scenicPendingsError: Error?
var roleApplies: [RoleApplyPendingResponse] = []
var roleAppliesError: Error?
func scenicListAll() async throws -> ScenicListAllResponse {
if let scenicListError { throw scenicListError }
return scenicList
}
func areas() async throws -> [ScenicAreaNode] { [] }
func scenicApplicationPendingAll() async throws -> ScenicApplicationPendingsResponse {
if let scenicPendingsError { throw scenicPendingsError }
return scenicPendings
}
func scenicSubmit(_ request: ScenicApplicationSubmitRequest) async throws {}
func scenicApplicationUploadPlaceholder(_ items: [ScenicApplicationUploadPlaceholder]) async throws {}
func roleApplyAll() async throws -> [RoleApplyPendingResponse] {
if let roleAppliesError { throw roleAppliesError }
return roleApplies
}
func roleApplySubmit(roleId: Int, scenicIds: [Int]) async throws {}
}
@MainActor
private final class ScenicSettlementSubmitMock: ScenicSettlementServing {
var requests: [ScenicSettlementSubmitRequest] = []
var errorAfterRequestCount: Int?
func scenicSettlementSubmit(_ request: ScenicSettlementSubmitRequest) async throws {
requests.append(request)
if let errorAfterRequestCount, requests.count >= errorAfterRequestCount {
throw TestError.sample
}
}
}
private enum TestError: LocalizedError {
case sample
var errorDescription: String? {
"测试错误"
}
}