修复账号切换后「我的」页当前账号展示错误,并统一举报摄影师首页 URI。
切换账号时以用户选中账号为准写入展示标题与业务作用域,避免沿用旧门店名称;同时将首页举报摄影师入口 URI 对齐为 report_photographer。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -147,6 +147,40 @@ final class AccountContextLoaderTests: XCTestCase {
|
||||
XCTAssertTrue(accountContext.storeScopes.isEmpty)
|
||||
XCTAssertNil(accountContext.currentStore)
|
||||
}
|
||||
|
||||
/// 测试门店接口失败时会保留登录/切换时已写入的门店作用域。
|
||||
func testRefreshSupplementalContextPreservesExistingStoreScopesWhenStoreAPIFails() async throws {
|
||||
let accountContext = AccountContext()
|
||||
accountContext.applyLogin(accountType: V9StoreUser.accountTypeValue)
|
||||
accountContext.replaceScopes(
|
||||
scenic: [BusinessScope(id: 88, name: "东湖景区", kind: .scenic)],
|
||||
stores: [BusinessScope(id: 66, name: "东湖门店", kind: .store, parentScenicId: 88)],
|
||||
currentScenicId: 88,
|
||||
currentStoreId: 66
|
||||
)
|
||||
let permissionContext = PermissionContext()
|
||||
let api = MockAccountContextAPI()
|
||||
api.roles = [
|
||||
RolePermissionResponse(
|
||||
role: RoleInfo(id: 7, name: "运营"),
|
||||
scenic: [ScenicInfo(id: 88, name: "东湖景区")]
|
||||
)
|
||||
]
|
||||
api.scenicResponse = ScenicListAllResponse(total: 1, list: [ScenicListItem(id: 88, name: "东湖景区")])
|
||||
api.storeError = APIError.networkFailed("门店接口失败")
|
||||
|
||||
try await AccountContextLoader().refreshSupplementalContext(
|
||||
accountContext: accountContext,
|
||||
permissionContext: permissionContext,
|
||||
profileAPI: MockUserProfileAPI(),
|
||||
accountContextAPI: api,
|
||||
cachedCurrentScenicId: 88,
|
||||
cachedCurrentStoreId: 66
|
||||
)
|
||||
|
||||
XCTAssertEqual(accountContext.storeScopes.map(\.name), ["东湖门店"])
|
||||
XCTAssertEqual(accountContext.currentStore?.name, "东湖门店")
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
|
||||
@ -46,6 +46,32 @@ final class AccountContextTests: XCTestCase {
|
||||
XCTAssertEqual(context.currentStore?.id, 20)
|
||||
}
|
||||
|
||||
/// 测试显式切换景区账号时会清空旧门店,而不是保留上一次门店选择。
|
||||
func testReplaceScopesExplicitSelectionClearsStoreForScenicAccount() {
|
||||
let context = AccountContext()
|
||||
context.replaceScopes(
|
||||
scenic: [BusinessScope(id: 128, name: "伊犁那拉提景区-5A", kind: .scenic)],
|
||||
stores: [BusinessScope(id: 37, name: "随心旅拍", kind: .store, parentScenicId: 128)],
|
||||
currentScenicId: 128,
|
||||
currentStoreId: 37,
|
||||
explicitSelection: true
|
||||
)
|
||||
XCTAssertEqual(context.currentStore?.name, "随心旅拍")
|
||||
|
||||
context.applyLogin(accountType: V9ScenicUser.accountTypeValue, businessUserId: 41, displayTitle: "伊犁那拉提景区-5A")
|
||||
context.replaceScopes(
|
||||
scenic: [BusinessScope(id: 128, name: "伊犁那拉提景区-5A", kind: .scenic)],
|
||||
stores: [BusinessScope(id: 37, name: "随心旅拍", kind: .store, parentScenicId: 128)],
|
||||
currentScenicId: 128,
|
||||
currentStoreId: nil,
|
||||
explicitSelection: true
|
||||
)
|
||||
|
||||
XCTAssertEqual(context.accountType, V9ScenicUser.accountTypeValue)
|
||||
XCTAssertNil(context.currentStore)
|
||||
XCTAssertEqual(context.currentAccountDisplayTitle, "伊犁那拉提景区-5A")
|
||||
}
|
||||
|
||||
/// 测试缓存 ID 不存在时会回退到首个可用作用域。
|
||||
func testReplaceScopesFallsBackToFirstScopeWhenCachedIdIsMissing() {
|
||||
let context = AccountContext()
|
||||
|
||||
@ -81,6 +81,69 @@ final class AuthModelsTests: XCTestCase {
|
||||
XCTAssertEqual(response.primaryProfile?.displayName, "示例门店")
|
||||
}
|
||||
|
||||
/// 测试切换门店账号时会优先使用 isCurrent 标记校准景区和门店作用域。
|
||||
func testV9AuthResponsePreferredScopeSelectionUsesCurrentStoreAccount() throws {
|
||||
let scenicJSON = """
|
||||
{
|
||||
"account_type": "scenic_user",
|
||||
"id": 101,
|
||||
"user_id": 101,
|
||||
"scenic_user_id": 101,
|
||||
"ss_user_id": 101,
|
||||
"username": "scenic_admin",
|
||||
"real_name": "张三",
|
||||
"nickname": "张三",
|
||||
"phone": "13800138000",
|
||||
"scenic_id": 1,
|
||||
"scenic_name": "旧景区",
|
||||
"is_current": false
|
||||
}
|
||||
"""
|
||||
let storeJSON = """
|
||||
{
|
||||
"account_type": "store_user",
|
||||
"id": 201,
|
||||
"user_id": 201,
|
||||
"store_user_id": 201,
|
||||
"username": "store_admin",
|
||||
"user_name": "store_admin",
|
||||
"real_name": "李四",
|
||||
"phone": "13800138000",
|
||||
"avatar": "",
|
||||
"scenic_id": 2,
|
||||
"scenic_name": "新景区",
|
||||
"store_id": 20,
|
||||
"store_name": "新门店",
|
||||
"is_current": true
|
||||
}
|
||||
"""
|
||||
let scenicUser = try JSONDecoder().decode(V9ScenicUser.self, from: Data(scenicJSON.utf8))
|
||||
let storeUser = try JSONDecoder().decode(V9StoreUser.self, from: Data(storeJSON.utf8))
|
||||
let response = V9AuthResponse(token: "token", scenicUsers: [scenicUser], storeUsers: [storeUser])
|
||||
|
||||
XCTAssertEqual(response.currentAccountIdentity?.accountType, V9StoreUser.accountTypeValue)
|
||||
XCTAssertEqual(response.currentAccountIdentity?.businessUserId, 201)
|
||||
XCTAssertEqual(response.preferredScopeSelection.scenicId, 2)
|
||||
XCTAssertEqual(response.preferredScopeSelection.storeId, 20)
|
||||
|
||||
let context = AccountContext()
|
||||
context.replaceScopes(
|
||||
scenic: [BusinessScope(id: 1, name: "旧景区", kind: .scenic)],
|
||||
stores: [],
|
||||
currentScenicId: 1,
|
||||
currentStoreId: nil
|
||||
)
|
||||
context.replaceScopes(
|
||||
scenic: response.scenicScopes,
|
||||
stores: response.storeScopes,
|
||||
currentScenicId: response.preferredScopeSelection.scenicId,
|
||||
currentStoreId: response.preferredScopeSelection.storeId
|
||||
)
|
||||
|
||||
XCTAssertEqual(context.currentScenic?.id, 2)
|
||||
XCTAssertEqual(context.currentStore?.id, 20)
|
||||
}
|
||||
|
||||
/// 测试 LoginRequest 会填充后端要求的默认字段。
|
||||
func testLoginRequestEncodesExpectedDefaults() throws {
|
||||
let request = LoginRequest(username: "18651857230", password: "secret123")
|
||||
|
||||
@ -16,14 +16,14 @@ final class HomeAllFunctionsBuilderTests: XCTestCase {
|
||||
topLevelPermissions: [
|
||||
permission(name: "基本信息", uri: "basic_info"),
|
||||
permission(name: "位置上报", uri: "location_report"),
|
||||
permission(name: "举报摄影师", uri: "photographer_report"),
|
||||
permission(name: "举报摄影师", uri: "report_photographer"),
|
||||
permission(name: "相册管理", uri: "album_list"),
|
||||
permission(name: "我的钱包", uri: "wallet")
|
||||
],
|
||||
commonURIs: []
|
||||
)
|
||||
|
||||
XCTAssertEqual(snapshot.allFunctions.map(\.uri), ["location_report", "photographer_report", "wallet"])
|
||||
XCTAssertEqual(snapshot.allFunctions.map(\.uri), ["location_report", "report_photographer", "wallet"])
|
||||
}
|
||||
|
||||
/// 测试保持 API 顶层顺序,不使用 preferredOrder 重排。
|
||||
|
||||
@ -269,20 +269,20 @@ final class HomeCommonMenuStoreTests: XCTestCase {
|
||||
XCTAssertEqual(uris, ["wallet", "message_center"])
|
||||
}
|
||||
|
||||
/// 测试 photographer_report 属于 Android menuList 白名单,且可加入常用应用。
|
||||
/// 测试 report_photographer 属于 Android menuList 白名单,且可加入常用应用。
|
||||
func testPhotographerReportIsWhitelistedAndCanBeAddedToCommon() {
|
||||
XCTAssertTrue(HomeCommonMenuStore.androidHomeMenuURIs.contains("photographer_report"))
|
||||
XCTAssertTrue(HomeCommonMenuStore.androidHomeMenuURIs.contains("report_photographer"))
|
||||
|
||||
let store = HomeCommonMenuStore(defaults: makeIsolatedDefaults())
|
||||
let uris = store.add(
|
||||
"photographer_report",
|
||||
"report_photographer",
|
||||
current: ["location_report"],
|
||||
topLevelPermissionURIs: ["location_report", "photographer_report"],
|
||||
topLevelPermissionURIs: ["location_report", "report_photographer"],
|
||||
roleCode: "photographer",
|
||||
accountScope: "scenic_user_photographer_report"
|
||||
accountScope: "scenic_user_report_photographer"
|
||||
)
|
||||
|
||||
XCTAssertEqual(uris, ["location_report", "photographer_report"])
|
||||
XCTAssertEqual(uris, ["location_report", "report_photographer"])
|
||||
}
|
||||
|
||||
/// 测试非白名单顶层项占用前 4 名额时,默认常用不会用后续白名单项补位。
|
||||
|
||||
@ -47,7 +47,7 @@ final class HomeMenuRouterTests: XCTestCase {
|
||||
("checkin_points", .destination(.punchPointList)),
|
||||
("location_report", .destination(.locationReport)),
|
||||
("location_report_history", .destination(.locationReportHistory)),
|
||||
("photographer_report", .destination(.photographerReport)),
|
||||
("report_photographer", .destination(.photographerReport)),
|
||||
("pm", .destination(.projectManagement)),
|
||||
("project_edit", .destination(.projectManagement)),
|
||||
("pm_manager", .destination(.pmProjectManagement)),
|
||||
@ -191,7 +191,7 @@ final class HomeMenuRouterTests: XCTestCase {
|
||||
XCTAssertTrue(uris.contains("sample_management"))
|
||||
XCTAssertTrue(uris.contains("checkin_points"))
|
||||
XCTAssertTrue(uris.contains("location_report"))
|
||||
XCTAssertTrue(uris.contains("photographer_report"))
|
||||
XCTAssertTrue(uris.contains("report_photographer"))
|
||||
XCTAssertTrue(uris.contains("pm"))
|
||||
XCTAssertTrue(uris.contains("pm_manager"))
|
||||
XCTAssertTrue(uris.contains("schedule_management"))
|
||||
@ -209,7 +209,7 @@ final class HomeMenuRouterTests: XCTestCase {
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "sample_upload", title: ""), .destination(.sampleUpload))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "checkin_points", title: ""), .destination(.punchPointList))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "location_report", title: ""), .destination(.locationReport))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "photographer_report", title: ""), .destination(.photographerReport))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "report_photographer", title: ""), .destination(.photographerReport))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "pm", title: ""), .destination(.projectManagement))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "pm_manager", title: ""), .destination(.pmProjectManagement))
|
||||
XCTAssertEqual(HomeMenuRouter.resolve(uri: "schedule_management", title: ""), .destination(.scheduleManagement))
|
||||
|
||||
Reference in New Issue
Block a user