迁移合作订单完整能力,并统一 AppRoleCode 角色权限与首页菜单展示。
新增 CooperationOrder 模块(双 Tab 列表、获客员绑定、主 Tab 扫码)、订单来源/带客单绑定及配套 API 测试;同步引入 roleCode 权限匹配与相关单元测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
93
suixinkanTests/AppRoleCodeTests.swift
Normal file
93
suixinkanTests/AppRoleCodeTests.swift
Normal file
@ -0,0 +1,93 @@
|
||||
//
|
||||
// AppRoleCodeTests.swift
|
||||
// suixinkanTests
|
||||
//
|
||||
// Created by Codex on 2026/6/29.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import suixinkan
|
||||
|
||||
final class AppRoleCodeTests: XCTestCase {
|
||||
func testFromCodeParsesKnownRoles() {
|
||||
XCTAssertEqual(AppRoleCode.fromCode("store_admin"), .storeAdmin)
|
||||
XCTAssertEqual(AppRoleCode.fromCode("scenic_admin"), .scenicAdmin)
|
||||
XCTAssertEqual(AppRoleCode.fromCode("photographer"), .photographer)
|
||||
}
|
||||
|
||||
func testFromLegacyRoleIdMapsKnownIds() {
|
||||
XCTAssertEqual(AppRoleCode.fromLegacyRoleId(46), .storeAdmin)
|
||||
XCTAssertEqual(AppRoleCode.fromLegacyRoleId(53), .scenicAdmin)
|
||||
XCTAssertEqual(AppRoleCode.fromLegacyRoleId(41), .photographer)
|
||||
}
|
||||
|
||||
func testFromRoleNameAvoidsAssistantMisclassification() {
|
||||
XCTAssertEqual(AppRoleCode.fromRoleName("摄影师助理"), .photographerAssistant)
|
||||
XCTAssertEqual(AppRoleCode.fromRoleName("资深摄影师"), .photographer)
|
||||
}
|
||||
|
||||
func testHomeMinimalTopRolesContainsManagementRoles() {
|
||||
XCTAssertTrue(AppRoleCode.homeMinimalTopRoles.contains(.storeAdmin))
|
||||
XCTAssertTrue(AppRoleCode.homeMinimalTopRoles.contains(.scenicAdmin))
|
||||
XCTAssertFalse(AppRoleCode.homeMinimalTopRoles.contains(.photographer))
|
||||
}
|
||||
}
|
||||
|
||||
final class RolePermissionMatchingTests: XCTestCase {
|
||||
func testMatchPrefersRoleCodeOverLegacyId() {
|
||||
let permissions = [
|
||||
RolePermissionResponse(
|
||||
role: RoleInfo(id: 10, name: "摄影师", roleCode: "photographer", notes: nil, permission: []),
|
||||
scenic: []
|
||||
),
|
||||
RolePermissionResponse(
|
||||
role: RoleInfo(id: 53, name: "景区管理员", roleCode: "scenic_admin", notes: nil, permission: []),
|
||||
scenic: []
|
||||
)
|
||||
]
|
||||
|
||||
let matched = RolePermissionMatching.match(
|
||||
in: permissions,
|
||||
roleCode: "scenic_admin",
|
||||
roleId: 10,
|
||||
roleName: "摄影师"
|
||||
)
|
||||
|
||||
XCTAssertEqual(matched?.role.id, 53)
|
||||
}
|
||||
|
||||
func testResolveRoleCodeMigratesLegacySession() {
|
||||
let resolved = RolePermissionMatching.resolveRoleCode(
|
||||
roleCode: nil,
|
||||
roleId: 46,
|
||||
roleName: nil,
|
||||
permissions: []
|
||||
)
|
||||
|
||||
XCTAssertEqual(resolved, .storeAdmin)
|
||||
}
|
||||
}
|
||||
|
||||
final class AccountSnapshotMigrationTests: XCTestCase {
|
||||
func testMigrateLegacyRoleIdToRoleCode() {
|
||||
var snapshot = AccountSnapshot(currentRoleId: 53)
|
||||
snapshot.migrateLegacyRoleIfNeeded()
|
||||
XCTAssertEqual(snapshot.currentRoleCode, "scenic_admin")
|
||||
XCTAssertNil(snapshot.currentRoleId)
|
||||
}
|
||||
|
||||
func testLoadMigratesAndPersistsLegacySnapshot() {
|
||||
let defaults = UserDefaults(suiteName: "AccountSnapshotMigrationTests")!
|
||||
defaults.removePersistentDomain(forName: "AccountSnapshotMigrationTests")
|
||||
let store = AccountSnapshotStore(defaults: defaults, key: "test.snapshot")
|
||||
store.save(AccountSnapshot(currentRoleId: 46))
|
||||
|
||||
let loaded = store.load()
|
||||
XCTAssertEqual(loaded?.currentRoleCode, "store_admin")
|
||||
XCTAssertNil(loaded?.currentRoleId)
|
||||
|
||||
let persisted = store.load()
|
||||
XCTAssertEqual(persisted?.currentRoleCode, "store_admin")
|
||||
XCTAssertNil(persisted?.currentRoleId)
|
||||
}
|
||||
}
|
||||
196
suixinkanTests/CooperationOrderAPITests.swift
Normal file
196
suixinkanTests/CooperationOrderAPITests.swift
Normal file
@ -0,0 +1,196 @@
|
||||
//
|
||||
// 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?.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)
|
||||
}
|
||||
}
|
||||
|
||||
/// 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) }
|
||||
})
|
||||
}
|
||||
24
suixinkanTests/Fixtures/cooperative_salers_success.json
Normal file
24
suixinkanTests/Fixtures/cooperative_salers_success.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"code": 100000,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"total": 1,
|
||||
"page": 1,
|
||||
"page_size": 50,
|
||||
"list": [
|
||||
{
|
||||
"bind_time": "2026-06-25 17:11:01",
|
||||
"binding_id": 5,
|
||||
"bound_at": "2026-06-25 17:11:01",
|
||||
"name": "管铜彬",
|
||||
"phone": "19281871413",
|
||||
"phone_masked": "192****1413",
|
||||
"sale_user_id": 101,
|
||||
"saler_name": "管铜彬",
|
||||
"saler_phone": "19281871413",
|
||||
"share_code": "INV-000101",
|
||||
"store_id": 37
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"code": 100000,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"total": "1",
|
||||
"list": [
|
||||
{
|
||||
"id": 801,
|
||||
"order_number": "ACQ001",
|
||||
"project_name": "亲子跟拍",
|
||||
"order_type": 11,
|
||||
"actual_pay_amount": "299.00",
|
||||
"customer_phone": "13700000003",
|
||||
"order_status_name": "已完成",
|
||||
"sale_user_name": "张三",
|
||||
"created_at": "2026-05-22 16:00:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
15
suixinkanTests/Fixtures/sale_user_invite_info_success.json
Normal file
15
suixinkanTests/Fixtures/sale_user_invite_info_success.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"code": 100000,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"is_bound": false,
|
||||
"photographer_name": "陆久银",
|
||||
"photographer_phone": "18651857230",
|
||||
"sale_user_id": 101,
|
||||
"saler_name": "管铜彬",
|
||||
"saler_phone": "13222319413",
|
||||
"share_code": "INV-000101",
|
||||
"subtitle": "确认与获客员绑定,可以绑定多个获客员",
|
||||
"title": "绑定获客员"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"code": 100000,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"total": "1",
|
||||
"list": [
|
||||
{
|
||||
"lead_id": 501,
|
||||
"user_phone": "13900000002",
|
||||
"remark": "景区门口获客",
|
||||
"created_at": "2026-05-21 14:00:00",
|
||||
"image_urls": ["https://example.com/lead.jpg"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
{
|
||||
"code": 100000,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"total": 1,
|
||||
"page": 1,
|
||||
"page_size": 50,
|
||||
"saler": {
|
||||
"sale_user_id": 101,
|
||||
"saler_name": "管铜彬",
|
||||
"saler_phone": "19281871413"
|
||||
},
|
||||
"list": [
|
||||
{
|
||||
"id": 54,
|
||||
"referral_order_no": "LD202606250009",
|
||||
"order_no": "LD202606250009",
|
||||
"user_mobile": "13322222223",
|
||||
"remark": "带客备注",
|
||||
"created_at": "2026-06-25 17:18:52",
|
||||
"status": 1,
|
||||
"status_label": "未完成",
|
||||
"images": [
|
||||
"https://vipsky.oss-cn-shanghai.aliyuncs.com/sales/referral-order/create/6/1782379129957_hd2z9x.jpg"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -10,38 +10,117 @@ import XCTest
|
||||
|
||||
/// 首页常用应用存储测试,覆盖默认值、过滤和别名去重。
|
||||
final class HomeCommonMenuStoreTests: XCTestCase {
|
||||
/// 测试首次无配置时会生成默认常用应用。
|
||||
func testLoadCreatesDefaultCommonMenusWhenBaselineIsMissing() {
|
||||
/// 测试首次无配置时会按顶层权限生成默认常用应用。
|
||||
func testLoadCreatesDefaultCommonMenusFromTopLevelPermissions() {
|
||||
let defaults = makeIsolatedDefaults()
|
||||
let store = HomeCommonMenuStore(defaults: defaults)
|
||||
let menus = [
|
||||
menu("registration_invitation"),
|
||||
menu("location_report"),
|
||||
menu("pm_manager")
|
||||
menu("space_settings"),
|
||||
menu("wallet"),
|
||||
menu("cloud_management"),
|
||||
menu("message_center")
|
||||
]
|
||||
|
||||
let uris = store.load(menuItems: menus)
|
||||
let uris = store.load(
|
||||
menuItems: menus,
|
||||
roleCode: "photographer",
|
||||
topLevelPermissionURIs: ["space_settings", "wallet", "cloud_management", "message_center"]
|
||||
)
|
||||
|
||||
XCTAssertEqual(uris, ["registration_invitation", "location_report", "pm_manager"])
|
||||
XCTAssertTrue(defaults.bool(forKey: HomeCommonMenuStore.defaultBaselineKey))
|
||||
XCTAssertEqual(uris, ["space_settings", "wallet", "cloud_management", "message_center"])
|
||||
XCTAssertEqual(
|
||||
defaults.stringArray(forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer"),
|
||||
["space_settings", "wallet", "cloud_management", "message_center"]
|
||||
)
|
||||
}
|
||||
|
||||
/// 测试顶层权限超过 4 个时只取前 4 个默认常用应用。
|
||||
func testDefaultCommonURIsTakeFirstFourWhenMoreThanFourPermissions() {
|
||||
let availableURIs: Set<String> = [
|
||||
"space_settings",
|
||||
"wallet",
|
||||
"cloud_management",
|
||||
"message_center",
|
||||
"task_management"
|
||||
]
|
||||
let uris = HomeCommonMenuStore.defaultCommonURIs(
|
||||
orderedTopLevelURIs: [
|
||||
"space_settings",
|
||||
"wallet",
|
||||
"cloud_management",
|
||||
"message_center",
|
||||
"task_management"
|
||||
],
|
||||
availableURIs: availableURIs
|
||||
)
|
||||
|
||||
XCTAssertEqual(uris, ["space_settings", "wallet", "cloud_management", "message_center"])
|
||||
}
|
||||
|
||||
/// 测试角色没有旧硬编码默认 URI 时仍能从权限列表生成常用应用。
|
||||
func testLoadCreatesDefaultsWithoutLegacyPreferredURIs() {
|
||||
let defaults = makeIsolatedDefaults()
|
||||
let store = HomeCommonMenuStore(defaults: defaults)
|
||||
let menus = [
|
||||
menu("space_settings"),
|
||||
menu("wallet"),
|
||||
menu("cloud_management")
|
||||
]
|
||||
|
||||
let uris = store.load(
|
||||
menuItems: menus,
|
||||
roleCode: "editor",
|
||||
topLevelPermissionURIs: ["space_settings", "wallet", "cloud_management"]
|
||||
)
|
||||
|
||||
XCTAssertEqual(uris, ["space_settings", "wallet", "cloud_management"])
|
||||
}
|
||||
|
||||
/// 测试已保存 URI 会按当前权限过滤并解析同义 URI。
|
||||
func testLoadFiltersSavedUrisByCurrentPermissions() {
|
||||
let defaults = makeIsolatedDefaults()
|
||||
defaults.set(true, forKey: HomeCommonMenuStore.defaultBaselineKey)
|
||||
defaults.set(["task_management", "unknown", "pm"], forKey: HomeCommonMenuStore.defaultStorageKey)
|
||||
defaults.set(["task_management", "unknown", "pm"], forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer")
|
||||
let store = HomeCommonMenuStore(defaults: defaults)
|
||||
let menus = [
|
||||
menu("task_management_editor"),
|
||||
menu("project_edit")
|
||||
]
|
||||
|
||||
let uris = store.load(menuItems: menus)
|
||||
let uris = store.load(
|
||||
menuItems: menus,
|
||||
roleCode: "photographer",
|
||||
topLevelPermissionURIs: ["task_management_editor", "project_edit"]
|
||||
)
|
||||
|
||||
XCTAssertEqual(uris, ["task_management_editor", "project_edit"])
|
||||
}
|
||||
|
||||
/// 测试不同角色使用独立存储 key。
|
||||
func testLoadUsesRoleScopedStorageKeys() {
|
||||
let defaults = makeIsolatedDefaults()
|
||||
defaults.set(["wallet"], forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer")
|
||||
defaults.set(["cloud_management"], forKey: HomeCommonMenuStore.storageKeyPrefix + "editor")
|
||||
let store = HomeCommonMenuStore(defaults: defaults)
|
||||
let menus = [
|
||||
menu("wallet"),
|
||||
menu("cloud_management")
|
||||
]
|
||||
|
||||
let roleOne = store.load(
|
||||
menuItems: menus,
|
||||
roleCode: "photographer",
|
||||
topLevelPermissionURIs: ["wallet", "cloud_management"]
|
||||
)
|
||||
let roleTwo = store.load(
|
||||
menuItems: menus,
|
||||
roleCode: "editor",
|
||||
topLevelPermissionURIs: ["wallet", "cloud_management"]
|
||||
)
|
||||
|
||||
XCTAssertEqual(roleOne, ["wallet"])
|
||||
XCTAssertEqual(roleTwo, ["cloud_management"])
|
||||
}
|
||||
|
||||
/// 测试添加常用应用时会按同义 URI 去重。
|
||||
func testAddDeduplicatesAliases() {
|
||||
let defaults = makeIsolatedDefaults()
|
||||
@ -50,7 +129,12 @@ final class HomeCommonMenuStoreTests: XCTestCase {
|
||||
menu("task_management_editor")
|
||||
]
|
||||
|
||||
let uris = store.add("task_management", current: ["task_management_editor"], menuItems: menus)
|
||||
let uris = store.add(
|
||||
"task_management",
|
||||
current: ["task_management_editor"],
|
||||
menuItems: menus,
|
||||
roleCode: "photographer"
|
||||
)
|
||||
|
||||
XCTAssertEqual(uris, ["task_management_editor"])
|
||||
}
|
||||
@ -60,11 +144,45 @@ final class HomeCommonMenuStoreTests: XCTestCase {
|
||||
let defaults = makeIsolatedDefaults()
|
||||
let store = HomeCommonMenuStore(defaults: defaults)
|
||||
|
||||
let uris = store.remove("pm", current: ["project_edit", "pm_manager", "location_report"])
|
||||
let uris = store.remove("pm", current: ["project_edit", "pm_manager", "location_report"], roleCode: "photographer")
|
||||
|
||||
XCTAssertEqual(uris, ["pm_manager", "location_report"])
|
||||
}
|
||||
|
||||
/// 测试无 role_code 时不读写常用应用。
|
||||
func testLoadReturnsEmptyWhenRoleCodeIsMissing() {
|
||||
let defaults = makeIsolatedDefaults()
|
||||
let store = HomeCommonMenuStore(defaults: defaults)
|
||||
|
||||
let uris = store.load(
|
||||
menuItems: [menu("wallet")],
|
||||
roleCode: nil,
|
||||
topLevelPermissionURIs: ["wallet"]
|
||||
)
|
||||
|
||||
XCTAssertTrue(uris.isEmpty)
|
||||
XCTAssertNil(defaults.stringArray(forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer"))
|
||||
}
|
||||
|
||||
/// 测试从 legacy role id key 一次性迁移常用菜单。
|
||||
func testLoadMigratesLegacyRoleIdStorageKey() {
|
||||
let defaults = makeIsolatedDefaults()
|
||||
defaults.set(["wallet", "cloud_management"], forKey: HomeCommonMenuStore.storageKeyPrefix + "46")
|
||||
let store = HomeCommonMenuStore(defaults: defaults)
|
||||
let menus = [menu("wallet"), menu("cloud_management")]
|
||||
|
||||
let uris = store.load(
|
||||
menuItems: menus,
|
||||
roleCode: "store_admin",
|
||||
legacyRoleId: 46,
|
||||
topLevelPermissionURIs: ["wallet", "cloud_management"]
|
||||
)
|
||||
|
||||
XCTAssertEqual(uris, ["wallet", "cloud_management"])
|
||||
XCTAssertEqual(defaults.stringArray(forKey: HomeCommonMenuStore.storageKeyPrefix + "store_admin"), ["wallet", "cloud_management"])
|
||||
XCTAssertNil(defaults.stringArray(forKey: HomeCommonMenuStore.storageKeyPrefix + "46"))
|
||||
}
|
||||
|
||||
/// 创建测试菜单实体。
|
||||
private func menu(_ uri: String) -> HomeMenuItem {
|
||||
HomeMenuItem(title: HomeMenuRouter.title(for: uri), uri: uri, iconSrc: nil)
|
||||
|
||||
@ -57,6 +57,7 @@ final class HomeMenuRouterTests: XCTestCase {
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "deposit_order", title: ""), .destination(.depositOrders))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "deposit_order_shooting_info", title: ""), .destination(.depositOrders))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "withdrawal_audit", title: ""), .destination(.withdrawalAudit))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "cooperation_order", title: ""), .destination(.cooperationOrder))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "scenic_settlement", title: ""), .destination(.scenicSettlement))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "scenic_settlement_review", title: ""), .destination(.scenicSettlementReview))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "message_center", title: ""), .destination(.messageCenter))
|
||||
@ -150,6 +151,7 @@ final class HomeMenuRouterTests: XCTestCase {
|
||||
func testPermissionRouteAuditSeparatesRoutableUnsupportedAndUnknownEntries() {
|
||||
let permissions = [
|
||||
rolePermission(
|
||||
roleCode: "photographer",
|
||||
roleId: 1,
|
||||
permissions: [
|
||||
permission(id: 1, name: "任务管理", uri: "task_management", children: [
|
||||
@ -162,7 +164,7 @@ final class HomeMenuRouterTests: XCTestCase {
|
||||
)
|
||||
]
|
||||
|
||||
let audit = HomePermissionRouteAuditor.audit(permissions: permissions, currentRoleId: 1)
|
||||
let audit = HomePermissionRouteAuditor.audit(permissions: permissions, currentRoleCode: "photographer")
|
||||
|
||||
XCTAssertEqual(audit.routable.map(\.uri), ["task_management", "task_create"])
|
||||
XCTAssertEqual(audit.unsupported.map(\.uri), ["pilot_controller"])
|
||||
@ -214,9 +216,9 @@ final class HomeMenuRouterTests: XCTestCase {
|
||||
#endif
|
||||
|
||||
/// 创建角色权限测试实体。
|
||||
private func rolePermission(roleId: Int, permissions: [PermissionItem]) -> RolePermissionResponse {
|
||||
private func rolePermission(roleCode: String, roleId: Int, permissions: [PermissionItem]) -> RolePermissionResponse {
|
||||
RolePermissionResponse(
|
||||
role: RoleInfo(id: roleId, name: "角色\(roleId)", permission: permissions),
|
||||
role: RoleInfo(id: roleId, name: "角色\(roleId)", roleCode: roleCode, permission: permissions),
|
||||
scenic: []
|
||||
)
|
||||
}
|
||||
|
||||
@ -15,15 +15,15 @@ final class HomeViewModelTests: XCTestCase {
|
||||
func testBuildMenusClearsStaleMenusWhenCurrentRoleIsMissing() {
|
||||
let viewModel = HomeViewModel()
|
||||
let permissions = [
|
||||
rolePermission(roleId: 1, permissions: [
|
||||
rolePermission(roleCode: "photographer", roleId: 1, permissions: [
|
||||
permission(id: 1, name: "消息中心", uri: "message_center")
|
||||
])
|
||||
]
|
||||
|
||||
viewModel.buildMenus(from: permissions, currentRoleId: 1)
|
||||
viewModel.buildMenus(from: permissions, currentRoleCode: "photographer")
|
||||
XCTAssertEqual(viewModel.menuItems.map(\.uri), ["message_center"])
|
||||
|
||||
viewModel.buildMenus(from: permissions, currentRoleId: 99)
|
||||
viewModel.buildMenus(from: permissions, currentRoleCode: "unknown_role")
|
||||
|
||||
XCTAssertTrue(viewModel.menuItems.isEmpty)
|
||||
}
|
||||
@ -32,15 +32,15 @@ final class HomeViewModelTests: XCTestCase {
|
||||
func testBuildMenusFallsBackToFirstRoleOnlyWhenCurrentRoleIsNil() {
|
||||
let viewModel = HomeViewModel()
|
||||
let permissions = [
|
||||
rolePermission(roleId: 1, permissions: [
|
||||
rolePermission(roleCode: "photographer", roleId: 1, permissions: [
|
||||
permission(id: 1, name: "任务管理", uri: "task_management")
|
||||
]),
|
||||
rolePermission(roleId: 2, permissions: [
|
||||
rolePermission(roleCode: "editor", roleId: 2, permissions: [
|
||||
permission(id: 2, name: "消息中心", uri: "message_center")
|
||||
])
|
||||
]
|
||||
|
||||
viewModel.buildMenus(from: permissions, currentRoleId: nil)
|
||||
viewModel.buildMenus(from: permissions, currentRoleCode: nil)
|
||||
|
||||
XCTAssertEqual(viewModel.menuItems.map(\.uri), ["task_management"])
|
||||
}
|
||||
@ -49,14 +49,14 @@ final class HomeViewModelTests: XCTestCase {
|
||||
func testBuildMenusFlattensPermissionTree() {
|
||||
let viewModel = HomeViewModel()
|
||||
let permissions = [
|
||||
rolePermission(roleId: 1, permissions: [
|
||||
rolePermission(roleCode: "photographer", roleId: 1, permissions: [
|
||||
permission(id: 1, name: "任务管理", uri: "task_management", children: [
|
||||
permission(id: 2, name: "消息中心", uri: "message_center")
|
||||
])
|
||||
])
|
||||
]
|
||||
|
||||
viewModel.buildMenus(from: permissions, currentRoleId: 1)
|
||||
viewModel.buildMenus(from: permissions, currentRoleCode: "photographer")
|
||||
|
||||
XCTAssertEqual(viewModel.menuItems.map(\.uri), ["task_management", "message_center"])
|
||||
}
|
||||
@ -65,7 +65,7 @@ final class HomeViewModelTests: XCTestCase {
|
||||
func testBuildMenusDeduplicatesKnownAndroidAliases() {
|
||||
let viewModel = HomeViewModel()
|
||||
let permissions = [
|
||||
rolePermission(roleId: 1, permissions: [
|
||||
rolePermission(roleCode: "photographer", roleId: 1, permissions: [
|
||||
permission(id: 1, name: "项目管理", uri: "pm_manager"),
|
||||
permission(id: 2, name: "项目管理旧入口", uri: "pm"),
|
||||
permission(id: 3, name: "收款码", uri: "payment_code"),
|
||||
@ -75,7 +75,7 @@ final class HomeViewModelTests: XCTestCase {
|
||||
])
|
||||
]
|
||||
|
||||
viewModel.buildMenus(from: permissions, currentRoleId: 1)
|
||||
viewModel.buildMenus(from: permissions, currentRoleCode: "photographer")
|
||||
|
||||
XCTAssertEqual(viewModel.menuItems.map(\.uri), ["pm", "deposit_order_detail", "pm_manager", "payment_code"])
|
||||
}
|
||||
@ -84,22 +84,22 @@ final class HomeViewModelTests: XCTestCase {
|
||||
func testBuildMenusSortsByPreferredOrder() {
|
||||
let viewModel = HomeViewModel()
|
||||
let permissions = [
|
||||
rolePermission(roleId: 1, permissions: [
|
||||
rolePermission(roleCode: "photographer", roleId: 1, permissions: [
|
||||
permission(id: 1, name: "消息中心", uri: "message_center"),
|
||||
permission(id: 2, name: "空间设置", uri: "space_settings"),
|
||||
permission(id: 3, name: "钱包", uri: "wallet")
|
||||
])
|
||||
]
|
||||
|
||||
viewModel.buildMenus(from: permissions, currentRoleId: 1)
|
||||
viewModel.buildMenus(from: permissions, currentRoleCode: "photographer")
|
||||
|
||||
XCTAssertEqual(viewModel.menuItems.map(\.uri), ["space_settings", "wallet", "message_center"])
|
||||
}
|
||||
|
||||
/// 创建角色权限测试实体。
|
||||
private func rolePermission(roleId: Int, permissions: [PermissionItem]) -> RolePermissionResponse {
|
||||
private func rolePermission(roleCode: String, roleId: Int, permissions: [PermissionItem]) -> RolePermissionResponse {
|
||||
RolePermissionResponse(
|
||||
role: RoleInfo(id: roleId, name: "角色\(roleId)", permission: permissions),
|
||||
role: RoleInfo(id: roleId, name: "角色\(roleId)", roleCode: roleCode, permission: permissions),
|
||||
scenic: []
|
||||
)
|
||||
}
|
||||
|
||||
@ -156,8 +156,17 @@ private func accountContext(scenicId: Int? = 88, storeId: Int? = 101) -> Account
|
||||
@MainActor
|
||||
private func permissionContext(roleName: String) -> PermissionContext {
|
||||
let context = PermissionContext()
|
||||
let role = RoleInfo(id: 1, name: roleName, permission: [PermissionItem(id: 1, name: "运营区域", uri: "operating-area")])
|
||||
context.replaceRolePermissions([RolePermissionResponse(role: role, scenic: [])], currentRoleId: 1)
|
||||
let roleCode = AppRoleCode.fromRoleName(roleName)?.rawValue ?? ""
|
||||
let role = RoleInfo(
|
||||
id: 1,
|
||||
name: roleName,
|
||||
roleCode: roleCode,
|
||||
permission: [PermissionItem(id: 1, name: "运营区域", uri: "operating-area")]
|
||||
)
|
||||
context.replaceRolePermissions(
|
||||
[RolePermissionResponse(role: role, scenic: [])],
|
||||
currentRoleCode: roleCode
|
||||
)
|
||||
return context
|
||||
}
|
||||
|
||||
|
||||
@ -17,10 +17,10 @@ final class OrdersViewModelTests: XCTestCase {
|
||||
api.storeResponses = [try TestFixture.payload(ListPayload<OrderEntity>.self, named: "order_v2_success")]
|
||||
let viewModel = OrdersViewModel()
|
||||
|
||||
try await viewModel.reloadStoreOrders(api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.reloadStoreOrders(api: api, scenicId: 88, appRole: nil)
|
||||
XCTAssertFalse(viewModel.storeOrders.isEmpty)
|
||||
|
||||
try await viewModel.reloadStoreOrders(api: api, scenicId: nil, roleId: nil)
|
||||
try await viewModel.reloadStoreOrders(api: api, scenicId: nil, appRole: nil)
|
||||
|
||||
XCTAssertTrue(viewModel.storeOrders.isEmpty)
|
||||
XCTAssertEqual(viewModel.storeTotal, 0)
|
||||
@ -35,8 +35,8 @@ final class OrdersViewModelTests: XCTestCase {
|
||||
api.storeResponses = [try TestFixture.payload(ListPayload<OrderEntity>.self, named: "order_v2_success")]
|
||||
let viewModel = OrdersViewModel()
|
||||
|
||||
try await viewModel.reloadStoreOrders(api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.loadMoreStoreOrders(api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.reloadStoreOrders(api: api, scenicId: 88, appRole: nil)
|
||||
try await viewModel.loadMoreStoreOrders(api: api, scenicId: 88, appRole: nil)
|
||||
|
||||
XCTAssertEqual(viewModel.storeOrders.count, 2)
|
||||
XCTAssertEqual(viewModel.storeTotal, 2)
|
||||
@ -58,13 +58,13 @@ final class OrdersViewModelTests: XCTestCase {
|
||||
viewModel.filterStartDate = Self.date("2026-05-01")
|
||||
viewModel.filterEndDate = Self.date("2026-05-31")
|
||||
|
||||
try await viewModel.reloadStoreOrders(api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.reloadStoreOrders(api: api, scenicId: 88, appRole: nil)
|
||||
|
||||
viewModel.selectedStatus = 30
|
||||
viewModel.searchPhone = " "
|
||||
viewModel.filterStartDate = nil
|
||||
viewModel.filterEndDate = nil
|
||||
try await viewModel.reloadStoreOrders(api: api, scenicId: 88, roleId: 53)
|
||||
try await viewModel.reloadStoreOrders(api: api, scenicId: 88, appRole: .scenicAdmin)
|
||||
|
||||
XCTAssertEqual(api.orderListCalls.count, 2)
|
||||
XCTAssertEqual(api.orderListCalls[0].page, 1)
|
||||
|
||||
42
suixinkanTests/SaleUserQrParserTests.swift
Normal file
42
suixinkanTests/SaleUserQrParserTests.swift
Normal file
@ -0,0 +1,42 @@
|
||||
//
|
||||
// SaleUserQrParserTests.swift
|
||||
// suixinkanTests
|
||||
//
|
||||
// Created by Codex on 2026/6/29.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import suixinkan
|
||||
|
||||
final class SaleUserQrParserTests: XCTestCase {
|
||||
/// 测试纯数字二维码解析。
|
||||
func testParsePlainNumber() {
|
||||
XCTAssertEqual(SaleUserQrParser.parseSaleUserId("12345"), 12345)
|
||||
}
|
||||
|
||||
/// 测试历史 JSON 格式解析。
|
||||
func testParseLegacyJSONWithoutMethod() {
|
||||
let json = #"{"sale_user_id":88}"#
|
||||
XCTAssertEqual(SaleUserQrParser.parseSaleUserId(json), 88)
|
||||
}
|
||||
|
||||
/// 测试标准 sale_user_bind 二维码。
|
||||
func testParseStandardSaleUserBindQR() {
|
||||
let json = #"{"method":"sale_user_bind","sale_user_id":2}"#
|
||||
XCTAssertEqual(SaleUserQrParser.parseSaleUserId(json), 2)
|
||||
XCTAssertTrue(SaleUserQrParser.isSaleUserBindQR(json))
|
||||
}
|
||||
|
||||
/// 测试 URL query 中的 sale_user_id。
|
||||
func testParseFromURLQuery() {
|
||||
let url = "https://example.com/bind?sale_user_id=99"
|
||||
XCTAssertEqual(SaleUserQrParser.parseSaleUserId(url), 99)
|
||||
}
|
||||
|
||||
/// 测试无效内容返回 nil。
|
||||
func testParseInvalidContentReturnsNil() {
|
||||
XCTAssertNil(SaleUserQrParser.parseSaleUserId("not-a-code"))
|
||||
XCTAssertNil(SaleUserQrParser.parseSaleUserId(""))
|
||||
XCTAssertFalse(SaleUserQrParser.isSaleUserBindQR("12345"))
|
||||
}
|
||||
}
|
||||
@ -101,7 +101,9 @@ final class ScenicSelectionViewModelTests: XCTestCase {
|
||||
currentScenicId: 1,
|
||||
currentStoreId: 10
|
||||
)
|
||||
permissionContext.replaceRolePermissions([RolePermissionResponse(role: RoleInfo(id: 7, name: "运营"), scenic: [])])
|
||||
permissionContext.replaceRolePermissions([
|
||||
RolePermissionResponse(role: RoleInfo(id: 7, name: "运营", roleCode: "scenic_operation"), scenic: [])
|
||||
], currentRoleCode: "scenic_operation")
|
||||
|
||||
ScenicSelectionViewModel().select(
|
||||
scenicId: 2,
|
||||
@ -114,6 +116,6 @@ final class ScenicSelectionViewModelTests: XCTestCase {
|
||||
XCTAssertEqual(accountContext.currentStore?.id, 20)
|
||||
XCTAssertEqual(snapshotStore.load()?.currentScenicId, 2)
|
||||
XCTAssertEqual(snapshotStore.load()?.currentStoreId, 20)
|
||||
XCTAssertEqual(snapshotStore.load()?.currentRoleId, 7)
|
||||
XCTAssertEqual(snapshotStore.load()?.currentRoleCode, "scenic_operation")
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ final class StatisticsViewModelTests: XCTestCase {
|
||||
api.dailyResponses = [try TestFixture.payload(DataListPayload<StatisticsDailyItem>.self, named: "statistics_daily_page1_total3")]
|
||||
let viewModel = StatisticsViewModel()
|
||||
|
||||
try await viewModel.reload(api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.reload(api: api, scenicId: 88, appRole: nil)
|
||||
|
||||
XCTAssertEqual(viewModel.summary.orderCount, 18)
|
||||
XCTAssertEqual(viewModel.dailyItems.map(\.date), ["2026-05-23"])
|
||||
@ -44,11 +44,11 @@ final class StatisticsViewModelTests: XCTestCase {
|
||||
]
|
||||
let viewModel = StatisticsViewModel()
|
||||
|
||||
try await viewModel.reload(api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.loadMore(api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.reload(api: api, scenicId: 88, appRole: nil)
|
||||
try await viewModel.loadMore(api: api, scenicId: 88, appRole: nil)
|
||||
XCTAssertEqual(viewModel.dailyItems.count, 3)
|
||||
|
||||
try await viewModel.selectPeriod(.sevenDays, api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.selectPeriod(.sevenDays, api: api, scenicId: 88, appRole: nil)
|
||||
|
||||
XCTAssertEqual(viewModel.selectedPeriod, .sevenDays)
|
||||
XCTAssertEqual(viewModel.dailyItems.map(\.date), ["2026-05-23"])
|
||||
@ -70,8 +70,8 @@ final class StatisticsViewModelTests: XCTestCase {
|
||||
]
|
||||
let viewModel = StatisticsViewModel()
|
||||
|
||||
try await viewModel.reload(api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.loadMore(api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.reload(api: api, scenicId: 88, appRole: nil)
|
||||
try await viewModel.loadMore(api: api, scenicId: 88, appRole: nil)
|
||||
|
||||
XCTAssertEqual(viewModel.dailyItems.map(\.date), ["2026-05-23", "2026-05-22", "2026-05-21"])
|
||||
XCTAssertFalse(viewModel.hasMore)
|
||||
@ -86,11 +86,11 @@ final class StatisticsViewModelTests: XCTestCase {
|
||||
api.dailyResponses = [try TestFixture.payload(DataListPayload<StatisticsDailyItem>.self, named: "statistics_daily_page1_total3")]
|
||||
let viewModel = StatisticsViewModel()
|
||||
|
||||
try await viewModel.reload(api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.reload(api: api, scenicId: 88, appRole: nil)
|
||||
api.nextDailyError = APIError.httpStatus(500, "server error")
|
||||
|
||||
do {
|
||||
try await viewModel.loadMore(api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.loadMore(api: api, scenicId: 88, appRole: nil)
|
||||
XCTFail("Expected load more to fail")
|
||||
} catch APIError.httpStatus(let statusCode, _) {
|
||||
XCTAssertEqual(statusCode, 500)
|
||||
@ -110,10 +110,10 @@ final class StatisticsViewModelTests: XCTestCase {
|
||||
api.dailyResponses = [try TestFixture.payload(DataListPayload<StatisticsDailyItem>.self, named: "statistics_daily_page1_total3")]
|
||||
let viewModel = StatisticsViewModel()
|
||||
|
||||
try await viewModel.reload(api: api, scenicId: 88, roleId: nil)
|
||||
try await viewModel.reload(api: api, scenicId: 88, appRole: nil)
|
||||
XCTAssertEqual(viewModel.summary.orderCount, 18)
|
||||
|
||||
try await viewModel.reload(api: api, scenicId: nil, roleId: nil)
|
||||
try await viewModel.reload(api: api, scenicId: nil, appRole: nil)
|
||||
|
||||
XCTAssertEqual(api.summaryCalls.count, 1)
|
||||
XCTAssertEqual(viewModel.summary.orderCount, 0)
|
||||
|
||||
Reference in New Issue
Block a user