// // OrderRefundDialogValidationTests.swift // suixinkanTests // import XCTest @testable import suixinkan final class OrderRefundDialogValidationTests: XCTestCase { func testPhotographerOrderRequiresRefundReason() { let result = OrderRefundDialogValidation.validate( kind: .photographerOrder, mode: .full, amountText: "", reason: "", fullRefundAmount: "88.00", maxRefundAmount: "88.00" ) XCTAssertEqual(failureMessage(from: result), "请输入退款原因") } func testPhotographerPartialRefundRequiresAmount() { let result = OrderRefundDialogValidation.validate( kind: .photographerOrder, mode: .partial, amountText: "", reason: "用户申请退款", fullRefundAmount: "88.00", maxRefundAmount: "88.00" ) XCTAssertEqual(failureMessage(from: result), "请输入退款金额") } func testStoreOrderRefundReasonLengthValidation() { let shortResult = OrderRefundDialogValidation.validate( kind: .storeOrder, mode: .full, amountText: "", reason: "太短", fullRefundAmount: "0", maxRefundAmount: "99.00" ) XCTAssertEqual(failureMessage(from: shortResult), "退款原因至少5个字符") let longResult = OrderRefundDialogValidation.validate( kind: .storeOrder, mode: .full, amountText: "", reason: String(repeating: "a", count: 256), fullRefundAmount: "0", maxRefundAmount: "99.00" ) XCTAssertEqual(failureMessage(from: longResult), "退款原因最多255个字符") } func testStoreOrderPartialRefundAmountValidation() { let emptyResult = OrderRefundDialogValidation.validate( kind: .storeOrder, mode: .partial, amountText: "", reason: "用户申请退款", fullRefundAmount: "0", maxRefundAmount: "99.00" ) XCTAssertEqual(failureMessage(from: emptyResult), "请输入退款金额") let invalidResult = OrderRefundDialogValidation.validate( kind: .storeOrder, mode: .partial, amountText: "0", reason: "用户申请退款", fullRefundAmount: "0", maxRefundAmount: "99.00" ) XCTAssertEqual(failureMessage(from: invalidResult), "请输入有效的退款金额") let overflowResult = OrderRefundDialogValidation.validate( kind: .storeOrder, mode: .partial, amountText: "100.00", reason: "用户申请退款", fullRefundAmount: "0", maxRefundAmount: "99.00" ) XCTAssertEqual(failureMessage(from: overflowResult), "退款金额不能大于实际支付金额") } func testStoreOrderFullRefundUsesZeroAmount() throws { let result = OrderRefundDialogValidation.validate( kind: .storeOrder, mode: .full, amountText: "99.00", reason: "用户申请退款", fullRefundAmount: "0", maxRefundAmount: "99.00" ) let payload = try successPayload(from: result) XCTAssertEqual(payload.refundType, OrderRefundMode.full.rawValue) XCTAssertEqual(payload.refundAmount, "0") XCTAssertEqual(payload.refundReason, "用户申请退款") } func testMoneyInputKeepsSingleDotAndTwoDecimalPlaces() { XCTAssertEqual(OrderRefundDialogValidation.filterMoneyInput("12..345a6", maxLength: 10), "12.34") XCTAssertEqual(OrderRefundDialogValidation.filterMoneyInput("12345678901", maxLength: 10), "1234567890") } private func failureMessage(from result: Result) -> String? { if case .failure(let error) = result { return error.message } return nil } private func successPayload( from result: Result ) throws -> OrderRefundDialogPayload { switch result { case .success(let payload): return payload case .failure(let error): XCTFail("Expected success, got failure: \(error.message)") throw NSError(domain: "OrderRefundDialogValidationTests", code: 1) } } }