Files
suixinkan_ios_new/suixinkanTests/StoreAdminOrderListViewModelTests.swift

225 lines
8.1 KiB
Swift
Raw 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.

//
// StoreAdminOrderListViewModelTests.swift
// suixinkanTests
//
// Created by Codex on 2026/6/29.
//
import XCTest
@testable import suixinkan
@MainActor
/// Tab ViewModel 退
final class StoreAdminOrderListViewModelTests: XCTestCase {
///
func testReloadClearsDataWhenStoreIsMissing() async throws {
let api = StoreAdminMockOrderService()
api.responses = [try TestFixture.payload(ListPayload<StoreOrderListItem>.self, named: "store_order_list_success")]
let viewModel = StoreAdminOrderListViewModel()
try await viewModel.reload(api: api, storeId: 66)
XCTAssertFalse(viewModel.orders.isEmpty)
try await viewModel.reload(api: api, storeId: nil)
XCTAssertTrue(viewModel.orders.isEmpty)
XCTAssertEqual(viewModel.total, 0)
XCTAssertEqual(viewModel.page, 1)
XCTAssertFalse(viewModel.hasMore)
XCTAssertEqual(api.listCalls.count, 1)
}
///
func testReloadUsesFilterQueries() async throws {
let api = StoreAdminMockOrderService()
api.responses = [
try TestFixture.payload(ListPayload<StoreOrderListItem>.self, named: "store_order_list_success"),
try TestFixture.payload(ListPayload<StoreOrderListItem>.self, named: "store_order_list_success")
]
let viewModel = StoreAdminOrderListViewModel()
viewModel.searchPhone = " 13800000000 "
viewModel.selectedStatus = 30
viewModel.filterStartDate = Self.date("2026-05-01")
viewModel.filterEndDate = Self.date("2026-05-31")
try await viewModel.reload(api: api, storeId: 66)
XCTAssertEqual(api.listCalls.count, 1)
XCTAssertEqual(api.listCalls[0].storeId, 66)
XCTAssertEqual(api.listCalls[0].userPhone, "13800000000")
XCTAssertEqual(api.listCalls[0].orderStatus, 30)
XCTAssertEqual(api.listCalls[0].startTime, "2026-05-01")
XCTAssertEqual(api.listCalls[0].endTime, "2026-05-31")
viewModel.selectedStatus = 0
viewModel.searchPhone = ""
try await viewModel.reload(api: api, storeId: 66)
XCTAssertEqual(api.listCalls[1].orderStatus, nil)
XCTAssertNil(api.listCalls[1].userPhone)
}
///
func testLoadMoreStopsAfterLastPage() async throws {
let api = StoreAdminMockOrderService()
api.responses = [try TestFixture.payload(ListPayload<StoreOrderListItem>.self, named: "store_order_list_success")]
let viewModel = StoreAdminOrderListViewModel()
try await viewModel.reload(api: api, storeId: 66)
try await viewModel.loadMore(api: api, storeId: 66)
XCTAssertEqual(viewModel.orders.count, 2)
XCTAssertEqual(api.listCalls.count, 1)
XCTAssertFalse(viewModel.hasMore)
}
/// 退
func testRefundUsesStoreParameters() async throws {
let api = StoreAdminMockOrderService()
let viewModel = StoreAdminOrderListViewModel()
try await viewModel.refund(
api: api,
storeId: 66,
orderNumber: "STORE001",
mode: .partial,
amount: "50.00",
reason: "部分退款"
)
XCTAssertEqual(api.refundCalls.count, 1)
XCTAssertEqual(api.refundCalls[0].storeId, 66)
XCTAssertEqual(api.refundCalls[0].orderNumber, "STORE001")
XCTAssertEqual(api.refundCalls[0].mode, .partial)
XCTAssertEqual(api.refundCalls[0].amount, "50.00")
XCTAssertEqual(api.refundCalls[0].reason, "部分退款")
}
private static func date(_ text: String) -> Date {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd"
return formatter.date(from: text)!
}
}
@MainActor
/// storeOrderList 退
private final class StoreAdminMockOrderService: OrderServing {
struct ListCall: Equatable {
let storeId: Int?
let page: Int
let userPhone: String?
let orderStatus: Int?
let startTime: String?
let endTime: String?
}
struct RefundCall: Equatable {
let storeId: Int
let orderNumber: String
let mode: OrderRefundMode
let amount: String
let reason: String
}
var responses: [ListPayload<StoreOrderListItem>] = []
private(set) var listCalls: [ListCall] = []
private(set) var refundCalls: [RefundCall] = []
func orderList(
scenicId: Int,
page: Int,
pageSize: Int,
orderStatus: Int?,
userPhone: String?,
startTime: String?,
endTime: String?,
isRefined: Int?,
isScenicAdmin: Bool
) async throws -> ListPayload<OrderEntity> {
ListPayload(total: 0, list: [])
}
func writeOffList(
scenicId: Int,
storeId: Int?,
page: Int,
pageSize: Int,
orderStatus: Int?,
orderVerifyStatus: Int?,
startTime: String?,
endTime: String?,
userPhone: String?
) async throws -> ListPayload<WriteOffOrderItem> {
ListPayload(total: 0, list: [])
}
func updateRefinedChoice(orderNumber: String, isRefined: Int) async throws {}
func cancelOrder(orderNumber: String) async throws {}
func sendGift(orderNumber: String, photoNum: Int, videoNum: Int) async throws {}
func storeOrderList(
storeId: Int?,
page: Int,
pageSize: Int,
userPhone: String?,
orderStatus: Int?,
orderType: Int?,
startTime: String?,
endTime: String?
) async throws -> ListPayload<StoreOrderListItem> {
listCalls.append(
ListCall(
storeId: storeId,
page: page,
userPhone: userPhone,
orderStatus: orderStatus,
startTime: startTime,
endTime: endTime
)
)
return responses.isEmpty ? ListPayload(total: 0, list: []) : responses.removeFirst()
}
func storeOrderRefund(
storeId: Int,
orderNumber: String,
refundType: OrderRefundMode,
refundAmount: String,
refundReason: String
) async throws {
refundCalls.append(
RefundCall(
storeId: storeId,
orderNumber: orderNumber,
mode: refundType,
amount: refundAmount,
reason: refundReason
)
)
}
func writeOff(orderNumber: String) async throws {}
func storeOrderDetail(storeId: Int, orderNumber: String) async throws -> StoreOrderDetailResponse {
try TestFixture.payload(StoreOrderDetailResponse.self, named: "store_order_detail_success")
}
func depositOrderList(scenicId: Int, page: Int, pageSize: Int) async throws -> ListPayload<DepositOrderListItem> {
ListPayload(total: 0, list: [])
}
func depositOrderWriteOff(orderNumber: String) async throws {}
func depositOrderRefund(orderNumber: String, refundReason: String) async throws {}
func storeOrderShootingDetail(
storeId: Int,
orderNumber: String,
scenicSpotId: Int,
photogUid: Int
) async throws -> StoreOrderShootingDetailResponse {
try TestFixture.payload(StoreOrderShootingDetailResponse.self, named: "store_order_shooting_detail_success")
}
func orderRefund(orderNumber: String, refundType: OrderRefundMode, refundAmount: String, refundReason: String) async throws {}
func multiTravelShootHistory(orderNumber: String) async throws -> MultiTravelShootHistoryResponse {
try TestFixture.payload(MultiTravelShootHistoryResponse.self, named: "multi_travel_shoot_history_success")
}
func multiTravelVerifiedScenicSpotList(orderNumber: String) async throws -> [MultiTravelVerifiedScenicSpotItem] { [] }
func multiTravelUploadMaterial(_ request: MultiTravelUploadMaterialRequest) async throws {}
}