// // HomeViewModelTests.swift // suixinkanTests // import XCTest @testable import suixinkan @MainActor /// 首页 ViewModel 测试。 final class HomeViewModelTests: XCTestCase { private var appStore: AppStore! private var defaults: UserDefaults! override func setUp() { defaults = UserDefaults(suiteName: "HomeViewModelTests")! defaults.removePersistentDomain(forName: "HomeViewModelTests") appStore = AppStore(defaults: defaults) appStore.userId = "2001" appStore.accountType = "scenic_user" appStore.roleCode = AppRoleCode.photographer.rawValue appStore.roleName = "摄影师" appStore.currentScenicId = 10 appStore.currentScenicName = "测试景区" } override func tearDown() { appStore.logout() super.tearDown() } func testMinimalTopRoleFlag() { appStore.roleCode = AppRoleCode.storeAdmin.rawValue let viewModel = HomeViewModel(appStore: appStore) viewModel.refreshLocalDisplayState() XCTAssertTrue(viewModel.isMinimalTopRole) appStore.roleCode = AppRoleCode.photographer.rawValue viewModel.refreshLocalDisplayState() XCTAssertFalse(viewModel.isMinimalTopRole) } func testLocationReportPromptDefaultsToFixedHomeCopy() { let viewModel = HomeViewModel(appStore: appStore) XCTAssertEqual(viewModel.locationInfoText, HomeViewModel.locationReportPromptText) XCTAssertEqual(viewModel.locationInfoText, "您已进入打卡范围") } func testRebuildCommonMenusFiltersUnknownURIs() { appStore.savePermissionItems([ HomePermissionItem(id: "1", name: "钱包", uri: "wallet"), HomePermissionItem(id: "2", name: "未知", uri: "unknown_uri"), ]) let viewModel = HomeViewModel(appStore: appStore) viewModel.rebuildCommonMenus() XCTAssertEqual(viewModel.commonMenus.map(\.uri), ["wallet"]) } func testRebuildCommonMenusPersistsDefaultURIsOnFirstLoad() { let menuStore = HomeCommonMenuStore(defaults: defaults) appStore.savePermissionItems([ HomePermissionItem(id: "1", name: "钱包", uri: "wallet"), HomePermissionItem(id: "2", name: "云盘", uri: "cloud_management"), HomePermissionItem(id: "3", name: "任务", uri: "task_management"), HomePermissionItem(id: "4", name: "设置", uri: "system_settings"), HomePermissionItem(id: "5", name: "消息", uri: "message_center"), ]) let viewModel = HomeViewModel(appStore: appStore, commonMenuStore: menuStore) viewModel.rebuildCommonMenus() XCTAssertEqual(viewModel.commonMenus.map(\.uri), [ "wallet", "cloud_management", "task_management", "system_settings", ]) XCTAssertEqual( menuStore.savedCommonURIs( accountScope: appStore.accountCachePrefix, roleCode: appStore.roleCode ), ["wallet", "cloud_management", "task_management", "system_settings"] ) } func testEmptyRolePermissionShowsPermissionDialog() async throws { let responseData = try TestJSON.envelope(data: [RolePermissionResponse]()) let session = MockURLSession(responses: [responseData]) let api = HomeAPI(client: APIClient(session: session)) let viewModel = HomeViewModel(appStore: appStore) await viewModel.loadPermissions(api: api, force: true) XCTAssertTrue(viewModel.showPermissionDialog) XCTAssertTrue(viewModel.commonMenus.isEmpty) } func testRolePermissionBuildsCommonMenusAndStoreCardRole() async throws { appStore.roleCode = AppRoleCode.storeAdmin.rawValue let permissionResponse = RolePermissionResponse( role: RoleInfo( id: 46, name: "店铺管理员", roleCode: AppRoleCode.storeAdmin.rawValue, notes: nil, permission: [ PermissionItem(id: 1, pid: 0, name: "钱包", uri: "wallet", iconSrc: nil, children: nil), PermissionItem(id: 2, pid: 0, name: "云盘", uri: "cloud_management", iconSrc: nil, children: nil), ] ), scenic: [ScenicInfo(id: 10, name: "测试景区", status: 1)] ) let storeResponse = StoreListResponse( total: 1, list: [StoreItem(id: 5, scenicId: 10, name: "测试门店", address: "地址", status: 1, statusText: "营业中")] ) let permissionJSON = try TestJSON.envelope(data: [permissionResponse]) let storeJSON = try TestJSON.envelope(data: storeResponse) let session = MockURLSession(responses: [permissionJSON, storeJSON]) let api = HomeAPI(client: APIClient(session: session)) let viewModel = HomeViewModel(appStore: appStore) await viewModel.loadPermissions(api: api, force: true) XCTAssertFalse(viewModel.showPermissionDialog) XCTAssertTrue(viewModel.isMinimalTopRole) XCTAssertEqual(viewModel.commonMenus.count, 2) XCTAssertEqual(viewModel.storeItem?.name, "测试门店") } func testMarkNeedsPermissionReload() async throws { let permissionResponse = RolePermissionResponse( role: RoleInfo( id: 41, name: "摄影师", roleCode: AppRoleCode.photographer.rawValue, notes: nil, permission: [ PermissionItem(id: 1, pid: 0, name: "钱包", uri: "wallet", iconSrc: nil, children: nil), ] ), scenic: [] ) appStore.savePermissionItems([HomePermissionItem(id: "1", name: "钱包", uri: "wallet")]) let permissionJSON = try TestJSON.envelope(data: [permissionResponse]) let session = MockURLSession(responses: [permissionJSON]) let api = HomeAPI(client: APIClient(session: session)) let viewModel = HomeViewModel(appStore: appStore) viewModel.markNeedsPermissionReload() await viewModel.reloadIfNeeded(api: api) XCTAssertEqual(viewModel.commonMenus.map(\.uri), ["wallet"]) XCTAssertEqual(session.requests.count, 1) } func testRefreshLocalDisplayStateClearsWhenNameMissing() { appStore.currentScenicId = 10 appStore.currentScenicName = "" let viewModel = HomeViewModel(appStore: appStore) viewModel.refreshLocalDisplayState() XCTAssertEqual(viewModel.currentScenicName, "") XCTAssertEqual(appStore.currentScenicId, 0) XCTAssertEqual(appStore.currentScenicName, "") } func testRefreshLocalDisplayStateClearsWhenIdMissing() { appStore.currentScenicId = 0 appStore.currentScenicName = "残留名称" let viewModel = HomeViewModel(appStore: appStore) viewModel.refreshLocalDisplayState() XCTAssertEqual(viewModel.currentScenicName, "") XCTAssertEqual(appStore.currentScenicName, "") } }