// // OrderListViewModelTests.swift // suixinkanTests // import XCTest @testable import suixinkan @MainActor final class OrderListViewModelTests: XCTestCase { override func tearDown() { AppStore.shared.roleCode = "" AppStore.shared.roleName = "" AppStore.shared.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.roleCode = AppRoleCode.scenicAdmin.rawValue let scenicVM = OrderListViewModel() XCTAssertEqual(scenicVM.listAPIPath, "/api/app/scenic-admin/order/list") XCTAssertTrue(scenicVM.isScenicAdminReadOnly) AppStore.shared.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>.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>.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") } }