Introduce real payment collection and wallet screens to replace home menu placeholders, wire APIs through RootView, and support bank card OSS uploads plus QR code saving to the photo library. Co-authored-by: Cursor <cursoragent@cursor.com>
153 lines
7.6 KiB
Swift
153 lines
7.6 KiB
Swift
//
|
||
// HomeMenuRouterTests.swift
|
||
// suixinkanTests
|
||
//
|
||
// Created by Codex on 2026/6/22.
|
||
//
|
||
|
||
import XCTest
|
||
@testable import suixinkan
|
||
|
||
/// 首页菜单路由测试,覆盖 URI 映射、别名和未知路由诊断。
|
||
final class HomeMenuRouterTests: XCTestCase {
|
||
override func setUp() {
|
||
super.setUp()
|
||
HomeRouteDiagnostics.resetUnknownRoutes()
|
||
}
|
||
|
||
override func tearDown() {
|
||
HomeRouteDiagnostics.resetUnknownRoutes()
|
||
super.tearDown()
|
||
}
|
||
|
||
/// 测试已迁移的首页路由会解析到真实目标。
|
||
func testMigratedRoutesResolveToDestinations() {
|
||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "space_settings", title: ""), .destination(.profileSpace))
|
||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "scenicselection", title: ""), .destination(.scenicSelection))
|
||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "store", title: ""), .destination(.moreFunctions))
|
||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "wallet", title: ""), .destination(.wallet))
|
||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "payment_collection", title: ""), .destination(.paymentCollection))
|
||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "payment_qr", title: ""), .destination(.paymentCollection))
|
||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "payment_code", title: ""), .destination(.paymentCollection))
|
||
}
|
||
|
||
/// 测试已知但未迁移的首页路由会进入安全占位。
|
||
func testKnownUnmigratedRoutesResolveToPlaceholders() {
|
||
XCTAssertEqual(
|
||
HomeMenuRouter.resolve(uri: "task_management", title: ""),
|
||
.destination(.modulePlaceholder(uri: "task_management", title: "任务管理"))
|
||
)
|
||
}
|
||
|
||
/// 测试 Tab 路由仍集中在 HomeMenuRouter。
|
||
func testTabRoutesStayCentralized() {
|
||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "photographer_orders", title: ""), .orders(.storeOrders))
|
||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "/scenic-order-manage", title: ""), .orders(.storeOrders))
|
||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "verification_order", title: ""), .orders(.verificationOrders))
|
||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "photographer_stats", title: ""), .tab(.statistics))
|
||
}
|
||
|
||
/// 测试飞控相关入口属于已知不支持范围。
|
||
func testFlightControlRoutesAreKnownUnsupportedScope() {
|
||
XCTAssertEqual(
|
||
HomeMenuRouter.resolve(uri: "fly", title: ""),
|
||
.unsupported(uri: "fly", title: "飞行管理", reason: "DJI/飞控模块已明确不纳入 iOS 迁移和后续开发范围。")
|
||
)
|
||
}
|
||
|
||
/// 测试未知 URI 会显式进入 placeholder。
|
||
func testUnknownRouteIsExplicitPlaceholder() {
|
||
XCTAssertEqual(
|
||
HomeMenuRouter.resolve(uri: "android_only_feature", title: "Android 专项"),
|
||
.placeholder(uri: "android_only_feature", title: "Android 专项")
|
||
)
|
||
}
|
||
|
||
/// 测试 canonicalURI 会使用当前权限可用的同义 URI。
|
||
func testCanonicalURIUsesAvailableAlias() {
|
||
let available: Set<String> = ["task_management_editor", "photographer_invite", "pm_manager", "payment_qr"]
|
||
XCTAssertEqual(HomeMenuRouter.canonicalURI(for: "task_management", availableURIs: available), "task_management_editor")
|
||
XCTAssertEqual(HomeMenuRouter.canonicalURI(for: "registration_invitation", availableURIs: available), "photographer_invite")
|
||
XCTAssertEqual(HomeMenuRouter.canonicalURI(for: "pm", availableURIs: available), "pm_manager")
|
||
XCTAssertEqual(HomeMenuRouter.canonicalURI(for: "payment_code", availableURIs: available), "payment_qr")
|
||
}
|
||
|
||
/// 测试 menuAliasKey 会把同义入口分到同一组。
|
||
func testMenuAliasKeyGroupsDuplicateAndroidEntries() {
|
||
XCTAssertEqual(HomeMenuRouter.menuAliasKey(for: "task_management_editor"), "task_management")
|
||
XCTAssertEqual(HomeMenuRouter.menuAliasKey(for: "photographer_invite"), "registration_invitation")
|
||
XCTAssertEqual(HomeMenuRouter.menuAliasKey(for: "pm_manager"), "pm")
|
||
XCTAssertEqual(HomeMenuRouter.menuAliasKey(for: "payment_code"), "payment_collection")
|
||
XCTAssertEqual(HomeMenuRouter.menuAliasKey(for: "deposit_order_shooting_info"), "deposit_order")
|
||
XCTAssertEqual(HomeMenuRouter.menuAliasKey(for: "/scenic-order-manage"), "photographer_orders")
|
||
XCTAssertEqual(HomeMenuRouter.menuAliasKey(for: "android_only_module"), "android_only_module")
|
||
}
|
||
|
||
/// 测试未知路由诊断会去重并更新标题。
|
||
func testUnknownRouteDiagnosticsDeduplicatesAndUpdatesTitle() {
|
||
HomeRouteDiagnostics.recordUnknown(uri: "android_feature", title: "旧标题")
|
||
HomeRouteDiagnostics.recordUnknown(uri: "android_feature", title: "新标题")
|
||
HomeRouteDiagnostics.recordUnknown(uri: "another_feature", title: "")
|
||
|
||
let records = HomeRouteDiagnostics.unknownRoutes()
|
||
|
||
XCTAssertEqual(records.count, 2)
|
||
XCTAssertEqual(records.first { $0.uri == "android_feature" }?.title, "新标题")
|
||
XCTAssertEqual(records.first { $0.uri == "android_feature" }?.count, 2)
|
||
XCTAssertEqual(records.first { $0.uri == "another_feature" }?.count, 1)
|
||
}
|
||
|
||
/// 测试未知路由诊断报告是 Markdown 且按出现次数排序。
|
||
func testUnknownRouteDiagnosticsReportIsMarkdownAndSortedByCount() {
|
||
HomeRouteDiagnostics.recordUnknown(uri: "rare_feature", title: "低频入口")
|
||
HomeRouteDiagnostics.recordUnknown(uri: "hot_feature", title: "高频入口")
|
||
HomeRouteDiagnostics.recordUnknown(uri: "hot_feature", title: "高频入口")
|
||
|
||
let report = HomeRouteDiagnostics.unknownRouteReport(generatedAt: Date(timeIntervalSince1970: 0))
|
||
|
||
XCTAssertTrue(report.contains("# Home Route Diagnostics"))
|
||
XCTAssertTrue(report.contains("| hot_feature | 高频入口 | 2 |"))
|
||
XCTAssertLessThan(
|
||
report.range(of: "hot_feature")!.lowerBound,
|
||
report.range(of: "rare_feature")!.lowerBound
|
||
)
|
||
}
|
||
|
||
/// 测试权限路由审计会区分可路由、不支持和未知入口。
|
||
func testPermissionRouteAuditSeparatesRoutableUnsupportedAndUnknownEntries() {
|
||
let permissions = [
|
||
rolePermission(
|
||
roleId: 1,
|
||
permissions: [
|
||
permission(id: 1, name: "任务管理", uri: "task_management", children: [
|
||
permission(id: 2, name: "发布任务", uri: "task_create")
|
||
]),
|
||
permission(id: 3, name: "飞控", uri: "pilot_controller"),
|
||
permission(id: 4, name: "Android 专项入口", uri: "android_only_module"),
|
||
permission(id: 5, name: "重复任务", uri: "task_management")
|
||
]
|
||
)
|
||
]
|
||
|
||
let audit = HomePermissionRouteAuditor.audit(permissions: permissions, currentRoleId: 1)
|
||
|
||
XCTAssertEqual(audit.routable.map(\.uri), ["task_management", "task_create"])
|
||
XCTAssertEqual(audit.unsupported.map(\.uri), ["pilot_controller"])
|
||
XCTAssertEqual(audit.unknown.map(\.uri), ["android_only_module"])
|
||
XCTAssertTrue(audit.hasUnknownRoutes)
|
||
}
|
||
|
||
/// 创建角色权限测试实体。
|
||
private func rolePermission(roleId: Int, permissions: [PermissionItem]) -> RolePermissionResponse {
|
||
RolePermissionResponse(
|
||
role: RoleInfo(id: roleId, name: "角色\(roleId)", permission: permissions),
|
||
scenic: []
|
||
)
|
||
}
|
||
|
||
/// 创建权限节点测试实体。
|
||
private func permission(id: Int, name: String, uri: String, children: [PermissionItem] = []) -> PermissionItem {
|
||
PermissionItem(id: id, name: name, uri: uri, children: children)
|
||
}
|
||
}
|