补充 Auth/Tasks/ScenicPermission/Live 单元测试,并完善 UI Test 登录与会话稳定性。
移除 LoginViewModel 硬编码账号,扩展登录流程测试覆盖;调整 ZLoginSmokeUITests 执行顺序与路由直达逻辑,避免清空 Keychain 影响其它用例。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
95
suixinkanTests/AuthModelsTests.swift
Normal file
95
suixinkanTests/AuthModelsTests.swift
Normal file
@ -0,0 +1,95 @@
|
||||
//
|
||||
// AuthModelsTests.swift
|
||||
// suixinkanTests
|
||||
//
|
||||
// Created by Codex on 2026/6/26.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import suixinkan
|
||||
|
||||
/// Auth 模块模型测试,覆盖 v9 登录响应解码和账号转换规则。
|
||||
final class AuthModelsTests: XCTestCase {
|
||||
/// 测试多账号登录 fixture 能正确解码并合并景区、门店账号。
|
||||
func testV9AuthResponseDecodesMultiAccountFixture() throws {
|
||||
let response = try TestFixture.payload(V9AuthResponse.self, named: "v9_login_multi_success")
|
||||
|
||||
XCTAssertEqual(response.token, "person-temp-token")
|
||||
XCTAssertEqual(response.scenicUsers.count, 1)
|
||||
XCTAssertEqual(response.storeUsers.count, 1)
|
||||
XCTAssertEqual(response.accounts.map(\.businessUserId), [101, 201])
|
||||
}
|
||||
|
||||
/// 测试景区账号会优先使用 ss_user_id 作为业务账号 ID。
|
||||
func testV9ScenicUserBusinessUserIdPrefersSsUserId() throws {
|
||||
let json = """
|
||||
{
|
||||
"account_type": "scenic_user",
|
||||
"id": 1,
|
||||
"user_id": 2,
|
||||
"scenic_user_id": 3,
|
||||
"ss_user_id": 101,
|
||||
"username": "scenic_admin",
|
||||
"real_name": "张三",
|
||||
"nickname": "张三",
|
||||
"phone": "13800138000",
|
||||
"scenic_id": 10,
|
||||
"scenic_name": "示例景区",
|
||||
"is_current": false
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
let user = try JSONDecoder().decode(V9ScenicUser.self, from: json)
|
||||
|
||||
XCTAssertEqual(user.businessUserId, 101)
|
||||
XCTAssertEqual(user.toAccountSwitchAccount().accountType, V9ScenicUser.accountTypeValue)
|
||||
XCTAssertEqual(user.toAccountSwitchAccount().toSetUserRequest(), SetUserRequest(ssUserId: 101))
|
||||
}
|
||||
|
||||
/// 测试门店账号会优先使用 store_user_id 作为业务账号 ID。
|
||||
func testV9StoreUserBusinessUserIdPrefersStoreUserId() throws {
|
||||
let json = """
|
||||
{
|
||||
"account_type": "store_user",
|
||||
"id": 1,
|
||||
"user_id": 2,
|
||||
"store_user_id": 201,
|
||||
"username": "store_admin",
|
||||
"user_name": "store_admin",
|
||||
"real_name": "张三",
|
||||
"phone": "13800138000",
|
||||
"avatar": "",
|
||||
"scenic_id": 10,
|
||||
"scenic_name": "示例景区",
|
||||
"store_id": 20,
|
||||
"store_name": "示例门店",
|
||||
"is_current": false
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
let user = try JSONDecoder().decode(V9StoreUser.self, from: json)
|
||||
|
||||
XCTAssertEqual(user.businessUserId, 201)
|
||||
XCTAssertEqual(user.toAccountSwitchAccount().accountType, V9StoreUser.accountTypeValue)
|
||||
XCTAssertEqual(user.toAccountSwitchAccount().toSetUserRequest(), SetUserRequest(storeUserId: 201))
|
||||
}
|
||||
|
||||
/// 测试登录响应会派生景区和门店作用域,并去重。
|
||||
func testV9AuthResponseDerivesScopesFromAccounts() throws {
|
||||
let response = try TestFixture.payload(V9AuthResponse.self, named: "v9_login_multi_success")
|
||||
|
||||
XCTAssertEqual(response.scenicScopes.map(\.id), [10])
|
||||
XCTAssertEqual(response.storeScopes.map(\.id), [20])
|
||||
XCTAssertEqual(response.primaryProfile?.displayName, "示例门店")
|
||||
}
|
||||
|
||||
/// 测试 LoginRequest 会填充后端要求的默认字段。
|
||||
func testLoginRequestEncodesExpectedDefaults() throws {
|
||||
let request = LoginRequest(username: "18651857230", password: "secret123")
|
||||
let json = try JSONSerialization.jsonObject(with: JSONEncoder().encode(request)) as? [String: Any]
|
||||
|
||||
XCTAssertEqual(json?["username"] as? String, "18651857230")
|
||||
XCTAssertEqual(json?["password"] as? String, "secret123")
|
||||
XCTAssertEqual(json?["type"] as? Int, 1)
|
||||
XCTAssertEqual(json?["mobile"] as? String, "")
|
||||
XCTAssertEqual(json?["code"] as? String, "")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user