216 lines
10 KiB
Swift
216 lines
10 KiB
Swift
//
|
||
// CooperationOrderAPITests.swift
|
||
// suixinkanTests
|
||
//
|
||
// Created by Codex on 2026/6/29.
|
||
//
|
||
|
||
import XCTest
|
||
@testable import suixinkan
|
||
|
||
@MainActor
|
||
/// 合作订单 API 测试,覆盖解码与请求参数。
|
||
final class CooperationOrderAPITests: XCTestCase {
|
||
/// 测试合作获客员列表解码与查询参数。
|
||
func testCooperativeSalersDecodesFixtureAndUsesExpectedQuery() async throws {
|
||
let session = CooperationRecordingURLSession(data: try TestFixture.data(named: "cooperative_salers_success"))
|
||
let api = CooperationOrderAPI(client: APIClient(session: session))
|
||
|
||
let response = try await api.cooperativeSalers(storeId: 66, page: 0, pageSize: 0)
|
||
|
||
XCTAssertEqual(response.total, 1)
|
||
XCTAssertEqual(response.page, 1)
|
||
XCTAssertEqual(response.pageSize, 50)
|
||
XCTAssertEqual(response.list.first?.displayId, 101)
|
||
XCTAssertEqual(response.list.first?.displayName, "张哥")
|
||
XCTAssertEqual(response.list.first?.photogRemarkName, "张哥")
|
||
XCTAssertEqual(response.list.first?.salerRealName, "管铜彬")
|
||
XCTAssertEqual(response.list.first?.displayPhone, "19281871413")
|
||
XCTAssertEqual(response.list.first?.bindingId, 5)
|
||
XCTAssertEqual(response.list.first?.shareCode, "INV-000101")
|
||
|
||
let request = try XCTUnwrap(session.requests.last)
|
||
XCTAssertEqual(request.httpMethod, "GET")
|
||
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/cooperative-salers")
|
||
let query = cooperationQueryItems(from: request)
|
||
XCTAssertEqual(query["store_id"], "66")
|
||
XCTAssertEqual(query["page"], "1")
|
||
XCTAssertEqual(query["page_size"], "1")
|
||
}
|
||
|
||
/// 测试获客员邀请信息解码。
|
||
func testSaleUserInviteInfoDecodesFixture() async throws {
|
||
let session = CooperationRecordingURLSession(data: try TestFixture.data(named: "sale_user_invite_info_success"))
|
||
let api = CooperationOrderAPI(client: APIClient(session: session))
|
||
|
||
let info = try await api.saleUserInviteInfo(saleUserId: 101)
|
||
|
||
XCTAssertEqual(info.saleUserId, 101)
|
||
XCTAssertFalse(info.isBound)
|
||
XCTAssertEqual(info.photographerName, "陆久银")
|
||
XCTAssertEqual(info.photographerPhone, "18651857230")
|
||
XCTAssertEqual(info.salerName, "管铜彬")
|
||
XCTAssertEqual(info.salerPhone, "13222319413")
|
||
XCTAssertEqual(info.shareCode, "INV-000101")
|
||
XCTAssertEqual(info.subtitle, "确认与获客员绑定,可以绑定多个获客员")
|
||
XCTAssertEqual(info.title, "绑定获客员")
|
||
|
||
let request = try XCTUnwrap(session.requests.last)
|
||
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/sale-user/invite-info")
|
||
XCTAssertEqual(cooperationQueryItems(from: request)["sale_user_id"], "101")
|
||
}
|
||
|
||
/// 测试获客线索列表解码。
|
||
func testSaleUserReferralLeadsDecodesFixture() async throws {
|
||
let session = CooperationRecordingURLSession(data: try TestFixture.data(named: "sale_user_referral_leads_success"))
|
||
let api = CooperationOrderAPI(client: APIClient(session: session))
|
||
|
||
let response = try await api.saleUserReferralLeads(page: 2, pageSize: 20)
|
||
|
||
XCTAssertEqual(response.total, 1)
|
||
XCTAssertEqual(response.list.first?.displayId, "501")
|
||
XCTAssertEqual(response.list.first?.displayPhone, "13900000002")
|
||
XCTAssertEqual(response.list.first?.remark, "景区门口获客")
|
||
XCTAssertEqual(response.list.first?.displayImages.first, "https://example.com/lead.jpg")
|
||
|
||
let request = try XCTUnwrap(session.requests.last)
|
||
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/sale-user/referral-leads")
|
||
let query = cooperationQueryItems(from: request)
|
||
XCTAssertEqual(query["page"], "2")
|
||
XCTAssertEqual(query["page_size"], "20")
|
||
}
|
||
|
||
/// 测试获客订单列表 keyword 查询。
|
||
func testSaleUserAcquisitionOrdersDecodesFixtureWithKeyword() async throws {
|
||
let session = CooperationRecordingURLSession(data: try TestFixture.data(named: "sale_user_acquisition_orders_success"))
|
||
let api = CooperationOrderAPI(client: APIClient(session: session))
|
||
|
||
let response = try await api.saleUserAcquisitionOrders(keyword: "138", page: 1, pageSize: 10)
|
||
|
||
XCTAssertEqual(response.total, 1)
|
||
XCTAssertEqual(response.list.first?.orderNumber, "ACQ001")
|
||
XCTAssertEqual(response.list.first?.displayAmount, "299.00")
|
||
XCTAssertEqual(response.list.first?.displayCustomerPhone, "13700000003")
|
||
XCTAssertEqual(response.list.first?.displayPartner, "张三")
|
||
|
||
let request = try XCTUnwrap(session.requests.last)
|
||
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/sale-user/acquisition-orders")
|
||
let query = cooperationQueryItems(from: request)
|
||
XCTAssertEqual(query["keyword"], "138")
|
||
}
|
||
|
||
/// 测试可绑定带客单列表解码。
|
||
func testSaleUserReferralOrdersDecodesFixture() async throws {
|
||
let session = CooperationRecordingURLSession(data: try TestFixture.data(named: "sale_user_referral_orders_success"))
|
||
let api = CooperationOrderAPI(client: APIClient(session: session))
|
||
|
||
let response = try await api.saleUserReferralOrders(saleUserId: 101, page: 1, pageSize: 10)
|
||
|
||
XCTAssertEqual(response.total, 1)
|
||
XCTAssertEqual(response.page, 1)
|
||
XCTAssertEqual(response.pageSize, 50)
|
||
XCTAssertEqual(response.saler?.saleUserId, 101)
|
||
XCTAssertEqual(response.saler?.salerName, "管铜彬")
|
||
XCTAssertEqual(response.list.first?.id, 54)
|
||
XCTAssertEqual(response.list.first?.displayReferralOrderNo, "LD202606250009")
|
||
XCTAssertEqual(response.list.first?.userMobile, "13322222223")
|
||
XCTAssertEqual(response.list.first?.remark, "带客备注")
|
||
XCTAssertEqual(response.list.first?.statusLabel, "未完成")
|
||
XCTAssertEqual(response.list.first?.images.count, 1)
|
||
|
||
let request = try XCTUnwrap(session.requests.last)
|
||
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/sale-user/referral-orders")
|
||
let query = cooperationQueryItems(from: request)
|
||
XCTAssertEqual(query["sale_user_id"], "101")
|
||
}
|
||
|
||
/// 测试接受绑定、绑定带客单与更新状态请求。
|
||
func testSaleUserAcceptBindAndBindReferralOrderUsePostQuery() async throws {
|
||
let emptyData = try TestFixture.data(named: "empty_success")
|
||
|
||
let acceptSession = CooperationRecordingURLSession(data: emptyData)
|
||
let acceptAPI = CooperationOrderAPI(client: APIClient(session: acceptSession))
|
||
try await acceptAPI.saleUserAcceptBind(saleUserId: 101)
|
||
|
||
let acceptRequest = try XCTUnwrap(acceptSession.requests.last)
|
||
XCTAssertEqual(acceptRequest.httpMethod, "POST")
|
||
XCTAssertEqual(acceptRequest.url?.path, "/api/yf-handset-app/photog/sale-user/accept-bind")
|
||
XCTAssertEqual(cooperationQueryItems(from: acceptRequest)["sale_user_id"], "101")
|
||
XCTAssertNil(acceptRequest.httpBody)
|
||
|
||
let bindSession = CooperationRecordingURLSession(data: emptyData)
|
||
let bindAPI = CooperationOrderAPI(client: APIClient(session: bindSession))
|
||
try await bindAPI.saleUserBindReferralOrder(orderNumber: "ORD001", referralOrderNo: "REF001")
|
||
|
||
let bindRequest = try XCTUnwrap(bindSession.requests.last)
|
||
XCTAssertEqual(bindRequest.httpMethod, "POST")
|
||
XCTAssertEqual(bindRequest.url?.path, "/api/yf-handset-app/photog/sale-user/bind-referral-order")
|
||
let bindQuery = cooperationQueryItems(from: bindRequest)
|
||
XCTAssertEqual(bindQuery["order_number"], "ORD001")
|
||
XCTAssertEqual(bindQuery["referral_order_no"], "REF001")
|
||
XCTAssertNil(bindRequest.httpBody)
|
||
|
||
let statusSession = CooperationRecordingURLSession(data: emptyData)
|
||
let statusAPI = CooperationOrderAPI(client: APIClient(session: statusSession))
|
||
try await statusAPI.saleUserUpdateReferralOrderStatus(id: 15, status: 3)
|
||
|
||
let statusRequest = try XCTUnwrap(statusSession.requests.last)
|
||
XCTAssertEqual(statusRequest.httpMethod, "POST")
|
||
XCTAssertEqual(
|
||
statusRequest.url?.path,
|
||
"/api/yf-handset-app/photog/sale-user/referral-orders/15/status"
|
||
)
|
||
let statusBody = try XCTUnwrap(statusRequest.httpBody)
|
||
let statusJSON = try XCTUnwrap(JSONSerialization.jsonObject(with: statusBody) as? [String: Any])
|
||
XCTAssertEqual(statusJSON["status"] as? Int, 3)
|
||
}
|
||
|
||
/// 测试更新合作获客员备注名请求体。
|
||
func testSaleUserUpdateRemarkUsesPostBody() async throws {
|
||
let emptyData = try TestFixture.data(named: "empty_success")
|
||
let session = CooperationRecordingURLSession(data: emptyData)
|
||
let api = CooperationOrderAPI(client: APIClient(session: session))
|
||
|
||
try await api.saleUserUpdateRemark(saleUserId: 123, photogRemarkName: "张哥")
|
||
|
||
let request = try XCTUnwrap(session.requests.last)
|
||
XCTAssertEqual(request.httpMethod, "POST")
|
||
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/sale-user/update-remark")
|
||
let body = try XCTUnwrap(request.httpBody)
|
||
let json = try XCTUnwrap(JSONSerialization.jsonObject(with: body) as? [String: Any])
|
||
XCTAssertEqual(json["sale_user_id"] as? Int, 123)
|
||
XCTAssertEqual(json["photog_remark_name"] as? String, "张哥")
|
||
}
|
||
}
|
||
|
||
/// URLSession 测试替身,记录合作订单 API 请求。
|
||
private final class CooperationRecordingURLSession: URLSessionProtocol {
|
||
let data: Data
|
||
var statusCode: Int
|
||
private(set) var requests: [URLRequest] = []
|
||
|
||
init(data: Data, statusCode: Int = 200) {
|
||
self.data = data
|
||
self.statusCode = statusCode
|
||
}
|
||
|
||
/// 返回固定数据和 HTTP 响应。
|
||
func data(for request: URLRequest) async throws -> (Data, URLResponse) {
|
||
requests.append(request)
|
||
return (
|
||
data,
|
||
HTTPURLResponse(url: request.url!, statusCode: statusCode, httpVersion: nil, headerFields: nil)!
|
||
)
|
||
}
|
||
}
|
||
|
||
private func cooperationQueryItems(from request: URLRequest) -> [String: String] {
|
||
guard let url = request.url,
|
||
let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
|
||
return [:]
|
||
}
|
||
return Dictionary(uniqueKeysWithValues: (components.queryItems ?? []).compactMap { item in
|
||
item.value.map { (item.name, $0) }
|
||
})
|
||
}
|