Add scenic selection and cooperation order flows aligned with Android.
Upgrade scenic picker with search, location sorting, permission apply/status, and blocking home dialog; add cooperation order module and order source picker improvements with unit tests. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
85
suixinkanTests/PermissionApplyViewModelTests.swift
Normal file
85
suixinkanTests/PermissionApplyViewModelTests.swift
Normal file
@ -0,0 +1,85 @@
|
||||
//
|
||||
// PermissionApplyViewModelTests.swift
|
||||
// suixinkanTests
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import suixinkan
|
||||
|
||||
@MainActor
|
||||
/// 权限申请 ViewModel 测试。
|
||||
final class PermissionApplyViewModelTests: XCTestCase {
|
||||
|
||||
private var appStore: AppStore!
|
||||
private var defaults: UserDefaults!
|
||||
|
||||
override func setUp() {
|
||||
defaults = UserDefaults(suiteName: "PermissionApplyViewModelTests")!
|
||||
defaults.removePersistentDomain(forName: "PermissionApplyViewModelTests")
|
||||
appStore = AppStore(defaults: defaults)
|
||||
appStore.saveRolePermissionList([
|
||||
RolePermissionResponse(
|
||||
role: RoleInfo(id: 10, name: "摄影师", roleCode: "PHOTOGRAPHER", notes: "拍摄"),
|
||||
scenic: [ScenicInfo(id: 100, name: "已有景区", status: 1)]
|
||||
),
|
||||
])
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
appStore.logout()
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testExistingScenicIsDisabledAfterLoad() async throws {
|
||||
let scenicJSON = """
|
||||
{"code":100000,"msg":"success","data":{"total":2,"list":[{"id":100,"name":"已有景区"},{"id":101,"name":"新景区"}]}}
|
||||
""".data(using: .utf8)!
|
||||
let api = HomeAPI(client: APIClient(environment: .testing, session: MockURLSession(responses: [scenicJSON])))
|
||||
let viewModel = PermissionApplyViewModel(appStore: appStore)
|
||||
viewModel.selectRole(RoleOption(id: 10, name: "摄影师", description: "拍摄", isSelected: true))
|
||||
|
||||
await viewModel.loadAvailableScenics(api: api)
|
||||
|
||||
let existing = viewModel.availableScenics.first { $0.id == 100 }
|
||||
let fresh = viewModel.availableScenics.first { $0.id == 101 }
|
||||
XCTAssertEqual(existing?.isDisabled, true)
|
||||
XCTAssertEqual(existing?.isSelected, true)
|
||||
XCTAssertEqual(fresh?.isDisabled, false)
|
||||
}
|
||||
|
||||
func testSubmitValidationRequiresRoleAndScenic() async {
|
||||
let api = HomeAPI(client: APIClient(environment: .testing, session: MockURLSession(responses: [])))
|
||||
let viewModel = PermissionApplyViewModel(appStore: appStore)
|
||||
var message: String?
|
||||
viewModel.onShowMessage = { message = $0 }
|
||||
|
||||
await viewModel.submit(api: api)
|
||||
XCTAssertEqual(message, "请先选择角色")
|
||||
|
||||
viewModel.selectRole(RoleOption(id: 10, name: "摄影师", description: "", isSelected: true))
|
||||
await viewModel.submit(api: api)
|
||||
XCTAssertEqual(message, "请至少选择一个景区")
|
||||
}
|
||||
|
||||
func testSubmitSuccessReturnsApplyCode() async throws {
|
||||
let scenicJSON = """
|
||||
{"code":100000,"msg":"success","data":{"total":1,"list":[{"id":101,"name":"新景区"}]}}
|
||||
""".data(using: .utf8)!
|
||||
let submitJSON = """
|
||||
{"code":100000,"msg":"success","data":{"code":"AP999"}}
|
||||
""".data(using: .utf8)!
|
||||
let api = HomeAPI(client: APIClient(environment: .testing, session: MockURLSession(responses: [scenicJSON, submitJSON])))
|
||||
let viewModel = PermissionApplyViewModel(appStore: appStore)
|
||||
viewModel.selectRole(RoleOption(id: 10, name: "摄影师", description: "", isSelected: true))
|
||||
await viewModel.loadAvailableScenics(api: api)
|
||||
if let scenic = viewModel.availableScenics.first(where: { $0.id == 101 }) {
|
||||
viewModel.toggleScenic(scenic)
|
||||
}
|
||||
|
||||
var applyCode: String?
|
||||
viewModel.onSubmitSuccess = { applyCode = $0 }
|
||||
await viewModel.submit(api: api)
|
||||
|
||||
XCTAssertEqual(applyCode, "AP999")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user