将会话、权限、位置、收款与排队存储拆分为独立模块,同步更新各 ViewModel 与单元测试,并补充素材管理 UI 与个人空间设置交互。 Co-authored-by: Cursor <cursoragent@cursor.com>
235 lines
8.5 KiB
Swift
235 lines
8.5 KiB
Swift
//
|
|
// OrderListViewModelTests.swift
|
|
// suixinkanTests
|
|
//
|
|
|
|
import XCTest
|
|
@testable import suixinkan
|
|
|
|
@MainActor
|
|
final class OrderListViewModelTests: XCTestCase {
|
|
|
|
override func tearDown() {
|
|
AppStore.shared.session.roleCode = ""
|
|
AppStore.shared.session.roleName = ""
|
|
AppStore.shared.session.currentScenicId = 0
|
|
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")
|
|
}
|
|
}
|