Align iOS home common apps and all-functions page with Android.

Add unified HomeCommonMenu/HomeAllFunctions diagnostics, rebuild all-functions from top-level menuList permissions, and document Home and AllFunctions module logic.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-30 09:40:02 +08:00
parent 63fb0462d6
commit 5692134efc
11 changed files with 693 additions and 138 deletions

View File

@ -0,0 +1,139 @@
//
// HomeAllFunctionsBuilderTests.swift
// suixinkanTests
//
// Created by Codex on 2026/6/30.
//
import XCTest
@testable import suixinkan
/// Android
final class HomeAllFunctionsBuilderTests: XCTestCase {
/// menuList URI
func testBuildFiltersToAndroidMenuListWhitelist() {
let snapshot = HomeAllFunctionsBuilder.build(
topLevelPermissions: [
permission(name: "基本信息", uri: "basic_info"),
permission(name: "位置上报", uri: "location_report"),
permission(name: "相册管理", uri: "album_list"),
permission(name: "我的钱包", uri: "wallet")
],
commonURIs: []
)
XCTAssertEqual(snapshot.allFunctions.map(\.uri), ["location_report", "wallet"])
}
/// API 使 preferredOrder
func testBuildPreservesTopLevelAPIOrder() {
let snapshot = HomeAllFunctionsBuilder.build(
topLevelPermissions: [
permission(name: "消息中心", uri: "message_center"),
permission(name: "空间设置", uri: "space_settings"),
permission(name: "我的钱包", uri: "wallet")
],
commonURIs: []
)
XCTAssertEqual(snapshot.allFunctions.map(\.uri), ["message_center", "space_settings", "wallet"])
}
///
func testBuildIgnoresChildPermissions() {
let snapshot = HomeAllFunctionsBuilder.build(
topLevelPermissions: [
permission(
name: "基本信息",
uri: "basic_info",
children: [permission(name: "消息中心", uri: "message_center")]
),
permission(name: "我的钱包", uri: "wallet")
],
commonURIs: []
)
XCTAssertEqual(snapshot.allFunctions.map(\.uri), ["wallet"])
}
/// / URI
func testBuildSplitsCommonAndMoreByExactURI() {
let snapshot = HomeAllFunctionsBuilder.build(
topLevelPermissions: [
permission(name: "位置上报", uri: "location_report"),
permission(name: "注册邀请", uri: "registration_invitation"),
permission(name: "店铺管理", uri: "store"),
permission(name: "飞行管理", uri: "fly")
],
commonURIs: ["registration_invitation", "location_report"]
)
XCTAssertEqual(snapshot.commonFunctions.map(\.uri), ["location_report", "registration_invitation"])
XCTAssertEqual(snapshot.moreFunctions.map(\.uri), ["store", "fly"])
}
/// allFunctions commonURIs
func testCommonFunctionsFollowAllFunctionsOrder() {
let snapshot = HomeAllFunctionsBuilder.build(
topLevelPermissions: [
permission(name: "位置上报", uri: "location_report"),
permission(name: "注册邀请", uri: "registration_invitation"),
permission(name: "店铺管理", uri: "store")
],
commonURIs: ["store", "location_report"]
)
XCTAssertEqual(snapshot.commonFunctions.map(\.uri), ["location_report", "store"])
}
/// Android
func testBuildMatchesAndroidSampleAccountShape() {
let topLevelURIs = [
"location_report",
"basic_info",
"registration_invitation",
"store",
"fly",
"space_settings",
"photographer_stats",
"photographer_orders",
"asset_management",
"schedule_management",
"system_settings",
"message_center",
"location_info",
"checkin_points",
"sample_management",
"live_album",
"live_stream_management",
"cloud_management",
"cooperation_order",
"scan_qr",
"payment_qr",
"wallet",
"pilot_cert",
"task_management_editor",
"pm_manager",
"pilot_controller",
"travel_album"
]
let snapshot = HomeAllFunctionsBuilder.build(
topLevelPermissions: topLevelURIs.map { permission(name: $0, uri: $0) },
commonURIs: ["location_report", "registration_invitation", "store"]
)
XCTAssertEqual(snapshot.allFunctions.count, 20)
XCTAssertEqual(snapshot.allFunctions.first?.uri, "location_report")
XCTAssertEqual(snapshot.commonFunctions.map(\.uri), ["location_report", "registration_invitation", "store"])
XCTAssertEqual(snapshot.moreFunctions.first?.uri, "fly")
XCTAssertEqual(snapshot.moreFunctions.count, 17)
}
private func permission(
name: String,
uri: String,
children: [PermissionItem] = []
) -> PermissionItem {
PermissionItem(id: uri.hashValue, name: name, uri: uri, children: children)
}
}

View File

@ -8,7 +8,7 @@
import XCTest
@testable import suixinkan
///
/// Android
final class HomeCommonMenuStoreTests: XCTestCase {
///
func testLoadCreatesDefaultCommonMenusFromTopLevelPermissions() {
@ -36,13 +36,6 @@ final class HomeCommonMenuStoreTests: XCTestCase {
/// 4 4
func testDefaultCommonURIsTakeFirstFourWhenMoreThanFourPermissions() {
let availableURIs: Set<String> = [
"space_settings",
"wallet",
"cloud_management",
"message_center",
"task_management"
]
let uris = HomeCommonMenuStore.defaultCommonURIs(
orderedTopLevelURIs: [
"space_settings",
@ -50,8 +43,7 @@ final class HomeCommonMenuStoreTests: XCTestCase {
"cloud_management",
"message_center",
"task_management"
],
availableURIs: availableURIs
]
)
XCTAssertEqual(uris, ["space_settings", "wallet", "cloud_management", "message_center"])
@ -76,10 +68,10 @@ final class HomeCommonMenuStoreTests: XCTestCase {
XCTAssertEqual(uris, ["space_settings", "wallet", "cloud_management"])
}
/// URI Android URI
/// URI
func testLoadFiltersSavedUrisByCurrentPermissions() {
let defaults = makeIsolatedDefaults()
defaults.set(["task_management", "unknown", "pm"], forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer")
defaults.set(["task_management_editor", "unknown", "pm"], forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer")
let store = HomeCommonMenuStore(defaults: defaults)
let menus = [
menu("task_management_editor"),
@ -95,6 +87,26 @@ final class HomeCommonMenuStoreTests: XCTestCase {
XCTAssertEqual(uris, ["task_management_editor"])
}
/// URI 退
func testSavedCommonDoesNotFallbackWhenAllInvalid() {
let defaults = makeIsolatedDefaults()
defaults.set(["task_management", "unknown"], forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer")
let store = HomeCommonMenuStore(defaults: defaults)
let menus = [menu("task_management_editor")]
let uris = store.load(
menuItems: menus,
roleCode: "photographer",
topLevelPermissionURIs: ["task_management_editor"]
)
XCTAssertTrue(uris.isEmpty)
XCTAssertEqual(
defaults.stringArray(forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer"),
["task_management", "unknown"]
)
}
/// 使
func testLoadUsesAccountScopedStorageKeys() {
let defaults = makeIsolatedDefaults()
@ -155,32 +167,29 @@ final class HomeCommonMenuStoreTests: XCTestCase {
XCTAssertEqual(roleTwo, ["cloud_management"])
}
/// URI
func testAddDeduplicatesAliases() {
/// 使 URI
func testAddUsesExactURIMatching() {
let defaults = makeIsolatedDefaults()
let store = HomeCommonMenuStore(defaults: defaults)
let menus = [
menu("task_management_editor")
]
let uris = store.add(
"task_management",
current: ["task_management_editor"],
menuItems: menus,
topLevelPermissionURIs: ["task_management_editor"],
roleCode: "photographer"
)
XCTAssertEqual(uris, ["task_management_editor"])
}
/// URI
func testRemoveDeletesAliases() {
/// 使 URI
func testRemoveUsesExactURIMatching() {
let defaults = makeIsolatedDefaults()
let store = HomeCommonMenuStore(defaults: defaults)
let uris = store.remove("pm", current: ["project_edit", "pm_manager", "location_report"], roleCode: "photographer")
XCTAssertEqual(uris, ["pm_manager", "location_report"])
XCTAssertEqual(uris, ["project_edit", "pm_manager", "location_report"])
}
/// role_code
@ -239,7 +248,7 @@ final class HomeCommonMenuStoreTests: XCTestCase {
XCTAssertNil(defaults.stringArray(forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer"))
}
/// Android URI
/// 4 menuList
func testDefaultCommonURIsExcludeMenusMissingFromAndroidCatalog() {
let defaults = makeIsolatedDefaults()
let store = HomeCommonMenuStore(defaults: defaults)
@ -260,6 +269,21 @@ final class HomeCommonMenuStoreTests: XCTestCase {
XCTAssertEqual(uris, ["wallet", "message_center"])
}
/// 4
func testDefaultCommonDoesNotBackfillAfterNonCatalogSlots() {
let uris = HomeCommonMenuStore.defaultCommonURIs(
orderedTopLevelURIs: [
"album_list",
"wallet",
"cloud_management",
"asset_management",
"task_management"
]
)
XCTAssertEqual(uris, ["wallet", "cloud_management", "asset_management"])
}
/// 4
func testSavedCommonURIsAreNotTruncatedToFour() {
let defaults = makeIsolatedDefaults()
@ -286,8 +310,8 @@ final class HomeCommonMenuStoreTests: XCTestCase {
XCTAssertEqual(uris, ["space_settings", "wallet", "cloud_management", "asset_management", "message_center"])
}
///
func testDefaultCommonURIsUseOnlyTopLevelPermissions() {
///
func testDefaultCommonUsesTopLevelOnlyNotFlattenedChildren() {
let defaults = makeIsolatedDefaults()
let store = HomeCommonMenuStore(defaults: defaults)
let menus = [
@ -305,6 +329,25 @@ final class HomeCommonMenuStoreTests: XCTestCase {
XCTAssertEqual(uris, ["task_management"])
}
/// menuItems
func testAvailableFunctionsIgnoreFlattenedChildPermissions() {
let defaults = makeIsolatedDefaults()
let store = HomeCommonMenuStore(defaults: defaults)
let menus = [
menu("wallet"),
menu("material_upload")
]
let uris = store.load(
menuItems: menus,
roleCode: "photographer",
accountScope: "scenic_user_101",
topLevelPermissionURIs: ["wallet"]
)
XCTAssertEqual(uris, ["wallet"])
}
///
private func menu(_ uri: String) -> HomeMenuItem {
HomeMenuItem(title: HomeMenuRouter.title(for: uri), uri: uri, iconSrc: nil)