Files
suixinkan_uikit/suixinkanTests/OrderListViewModelTests.swift
汉秋 c083f1d4b3 升级 AppStore 缓存 Key 并在覆盖安装时强制重新登录。
统一账号作用域 Key 对齐 Android,新增缓存 schema 迁移清理旧数据,并同步更新相关模块与单元测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 09:35:55 +08:00

239 lines
8.6 KiB
Swift

//
// OrderListViewModelTests.swift
// suixinkanTests
//
import XCTest
@testable import suixinkan
@MainActor
final class OrderListViewModelTests: XCTestCase {
override func setUp() {
super.setUp()
AppStore.shared.logout()
AppStore.shared.session.configureTestAccount(userId: "order-list-user", scenicId: 10)
}
override func tearDown() {
AppStore.shared.logout()
super.tearDown()
}
func testOrderStatusQueryMapping() {
XCTAssertNil(OrderListQueryBuilder.orderStatusQuery(tabIndex: 0))
XCTAssertEqual(OrderListQueryBuilder.orderStatusQuery(tabIndex: 18), "18")
XCTAssertEqual(OrderListQueryBuilder.orderStatusQuery(tabIndex: 30), "30")
}
func testIsRefinedQueryMapping() {
XCTAssertNil(OrderListQueryBuilder.isRefinedQuery(rTabIndex: 0))
XCTAssertEqual(OrderListQueryBuilder.isRefinedQuery(rTabIndex: 1), 1)
XCTAssertEqual(OrderListQueryBuilder.isRefinedQuery(rTabIndex: 2), 2)
}
func testPhotographerFilterLabels() {
let viewModel = OrderListViewModel()
viewModel.onFilterChange(orderStatus: 18, isRefined: 0)
XCTAssertEqual(viewModel.filterLabel, "已付定金")
viewModel.onFilterChange(orderStatus: 0, isRefined: 1)
XCTAssertEqual(viewModel.filterLabel, "需要精修")
}
func testRoleRoutingPath() {
AppStore.shared.session.roleCode = AppRoleCode.scenicAdmin.rawValue
let scenicVM = OrderListViewModel()
XCTAssertEqual(scenicVM.listAPIPath, "/api/app/scenic-admin/order/list")
XCTAssertTrue(scenicVM.isScenicAdminReadOnly)
AppStore.shared.session.roleCode = AppRoleCode.photographer.rawValue
let photoVM = OrderListViewModel()
XCTAssertEqual(photoVM.listAPIPath, "/api/yf-handset-app/photog/order/listv2")
XCTAssertFalse(photoVM.isScenicAdminReadOnly)
}
func testLoadMoreBoundary() {
let viewModel = OrderListViewModel()
XCTAssertFalse(viewModel.shouldLoadMore(at: 0))
}
func testOrderEntityDecodesPhotoTravel() throws {
let json = """
{
"code": 100000,
"msg": "success",
"data": {
"total": 1,
"list": [{
"order_number": "NO001",
"order_status": 18,
"order_status_name": "",
"actual_pay_amount": "99.00",
"photo_travel": {
"order_photo_num": 10,
"order_video_num": 1,
"need_check_in": true,
"can_cancel_order": true
}
}]
}
}
""".data(using: .utf8)!
let envelope = try JSONDecoder().decode(APIEnvelope<OrderListResponse<OrderEntity>>.self, from: json)
let order = try XCTUnwrap(envelope.data?.list.first)
XCTAssertEqual(order.orderNumber, "NO001")
XCTAssertEqual(order.photoTravel?.orderPhotoNum, 10)
XCTAssertEqual(order.photoTravel?.needCheckIn, true)
}
func testOrderListDecodesRealAPIResponseShape() throws {
let json = """
{
"code": 100000,
"msg": "success",
"data": {
"total": 3,
"list": [
{
"actual_pay_amount": "0.01",
"created_at": "2026-06-25 17:12:24",
"is_refined": 1,
"multi_travel": {},
"order_number": "260625128009",
"order_status": 30,
"order_status_name": "",
"order_type": 14,
"order_type_label": "线",
"phone": "13222319413",
"photo_travel": {},
"project_name": "线",
"referral_order": {
"bind_order_number": "260625128009",
"created_at": "2026-06-25 17:13:51",
"display_text": "1234567 19281871413",
"id": 53,
"order_no": "LD202606250008",
"sale_user": {
"display_name": "1234567",
"name": "1234567",
"photog_remark_name": "1234567",
"sale_user_id": 6,
"saler_name": "1234567"
},
"sale_user_id": 6,
"saler_name": "1234567",
"saler_phone": "19281871413",
"source_type": 2,
"source_type_label": "线",
"status": 2,
"status_label": "",
"user_mobile": "13333333331"
},
"user_id": 141943
},
{
"actual_pay_amount": "0.01",
"created_at": "2026-06-17 14:08:37",
"is_refined": 2,
"multi_travel": {},
"order_number": "260617128001",
"order_status": 50,
"order_status_name": "退",
"order_type": 11,
"phone": "18651857230",
"photo_travel": {
"can_cancel_order": false,
"can_gift_retouch": false,
"need_check_in": true,
"order_photo_num": 6,
"order_video_num": 0,
"retouch_gift_photo_num": 2,
"retouch_gift_time": "2026-06-23 11:29:33",
"retouch_gift_video_num": 0
},
"project_name": " - 便",
"user_id": 143089
}
]
}
}
""".data(using: .utf8)!
let envelope = try JSONDecoder().decode(APIEnvelope<OrderListResponse<OrderEntity>>.self, from: json)
let list = try XCTUnwrap(envelope.data?.list)
XCTAssertEqual(list.count, 2)
XCTAssertNil(list[0].photoTravel)
XCTAssertNil(list[0].multiTravel)
XCTAssertEqual(list[0].referralOrder?.orderNo, "LD202606250008")
XCTAssertEqual(list[0].referralOrder?.photogRemarkName, "管铜彬1234567")
XCTAssertEqual(list[1].photoTravel?.orderPhotoNum, 6)
XCTAssertEqual(list[1].photoTravel?.needCheckIn, true)
}
func testReferralOrderEntityDecodesImages() throws {
let json = """
{
"id": 1,
"referral_order_no": "LD001",
"order_no": "LD001",
"user_mobile": "13800138000",
"remark": "",
"created_at": "2026-06-25",
"status": 1,
"status_label": "",
"images": ["https://cdn.example.com/a.jpg", "https://cdn.example.com/b.jpg"]
}
""".data(using: .utf8)!
let entity = try JSONDecoder().decode(ReferralOrderEntity.self, from: json)
XCTAssertEqual(entity.images.count, 2)
XCTAssertEqual(OrderSourceMapping.lead(from: entity).remark, "")
}
func testOrderSourceLeadMappingUsesStatusLabelFallback() throws {
let json = """
{
"id": 1,
"referral_order_no": "LD002",
"order_no": "LD002",
"user_mobile": "13800138000",
"remark": "",
"created_at": "",
"status": 1,
"status_label": "已完成",
"images": []
}
""".data(using: .utf8)!
let entity = try JSONDecoder().decode(ReferralOrderEntity.self, from: json)
XCTAssertEqual(OrderSourceMapping.lead(from: entity).remark, "")
}
func testOrderSourceSelectionFromBoundReferralUsesRemarkFallback() throws {
let json = """
{
"id": 53,
"order_no": "LD202606250008",
"sale_user_id": 6,
"saler_name": "管铜彬",
"photog_remark_name": "管铜彬1234567",
"saler_phone": "19281871413",
"display_text": "管铜彬1234567 19281871413",
"user_mobile": "13333333331",
"remark": "",
"bind_order_number": "260625128009",
"source_type": 2,
"source_type_label": "下级线索",
"status": 2,
"status_label": "已完成",
"created_at": "2026-06-25 17:13:51"
}
""".data(using: .utf8)!
let referral = try JSONDecoder().decode(BoundReferralOrderEntity.self, from: json)
let selection = OrderSourceMapping.selection(from: referral)
XCTAssertEqual(selection?.person.name, "1234567")
XCTAssertEqual(selection?.lead.remark, "1234567 19281871413")
XCTAssertEqual(selection?.lead.key, "LD202606250008")
}
}