Files
suixinkan_uikit/suixinkanTests/PaymentCollectionDetailsViewModelTests.swift
汉秋 005349f8e6 模块化 AppStore 并完善素材管理与个人空间设置。
将会话、权限、位置、收款与排队存储拆分为独立模块,同步更新各 ViewModel 与单元测试,并补充素材管理 UI 与个人空间设置交互。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-13 11:01:08 +08:00

95 lines
3.4 KiB
Swift

//
// PaymentCollectionDetailsViewModelTests.swift
// suixinkanTests
//
import XCTest
@testable import suixinkan
/// ViewModel
@MainActor
final class PaymentCollectionDetailsViewModelTests: XCTestCase {
private var appStore: AppStore!
override func setUp() {
let defaults = UserDefaults(suiteName: "PaymentCollectionDetailsViewModelTests")!
defaults.removePersistentDomain(forName: "PaymentCollectionDetailsViewModelTests")
appStore = AppStore(defaults: defaults)
appStore.session.userId = "10001"
appStore.session.currentScenicId = 10
appStore.session.currentScenicName = "测试景区"
}
override func tearDown() {
appStore.logout()
super.tearDown()
}
func testPaymentAmountValidatorRejectsEmptyAmount() {
XCTAssertEqual(PaymentAmountValidator.validationMessage(for: ""), "请输入收款金额")
}
func testPaymentAmountValidatorRejectsZeroAmount() {
XCTAssertEqual(PaymentAmountValidator.validationMessage(for: "0"), "请输入有效的收款金额")
}
func testPaymentAmountValidatorRejectsMoreThanTwoDecimals() {
XCTAssertEqual(PaymentAmountValidator.validationMessage(for: "1.234"), "金额最多支持两位小数")
}
func testPaymentAmountValidatorAcceptsValidAmount() {
XCTAssertNil(PaymentAmountValidator.validationMessage(for: "12.50"))
}
func testShowSetAmountDialogRequiresPayCode() {
let viewModel = PaymentCollectionDetailsViewModel(appStore: appStore)
var message: String?
viewModel.onShowMessage = { message = $0 }
viewModel.showSetAmountDialog()
XCTAssertEqual(message, "请先获取收款码")
XCTAssertFalse(viewModel.showAmountDialog)
}
func testConfirmAmountBuildsDynamicURL() async throws {
let payCodeJSON = """
{"code":100000,"msg":"success","data":{"static_pay_url":"https://pay.example.com/static","dynamic_pay_url":"https://pay.example.com/dynamic"}}
""".data(using: .utf8)!
let session = MockURLSession(responses: [payCodeJSON])
let api = PaymentAPI(client: APIClient(environment: .testing, session: session))
let viewModel = PaymentCollectionDetailsViewModel(appStore: appStore)
await viewModel.loadPayCode(api: api)
viewModel.updateAmount("88.50")
viewModel.updateRemark("")
viewModel.confirmAmount()
XCTAssertTrue(viewModel.hasPayCode)
XCTAssertFalse(viewModel.showAmountDialog)
}
func testToggleReceiveVoicePersistsInAppStore() {
let viewModel = PaymentCollectionDetailsViewModel(appStore: appStore)
viewModel.refreshLocalState()
XCTAssertFalse(viewModel.isVoiceBroadcastOpen)
viewModel.toggleReceiveVoice()
XCTAssertTrue(appStore.payment.isOpenReceiveVoice)
XCTAssertTrue(viewModel.isVoiceBroadcastOpen)
}
func testLoadPayCodeClearsQRWhenScenicMissing() async {
appStore.session.currentScenicId = 0
let session = MockURLSession(responses: [])
let api = PaymentAPI(client: APIClient(environment: .testing, session: session))
let viewModel = PaymentCollectionDetailsViewModel(appStore: appStore)
await viewModel.loadPayCode(api: api)
XCTAssertFalse(viewModel.hasPayCode)
XCTAssertEqual(session.requests.count, 0)
}
}