将会话、权限、位置、收款与排队存储拆分为独立模块,同步更新各 ViewModel 与单元测试,并补充素材管理 UI 与个人空间设置交互。 Co-authored-by: Cursor <cursoragent@cursor.com>
152 lines
5.4 KiB
Swift
152 lines
5.4 KiB
Swift
//
|
|
// HomeLocationStateStoreTests.swift
|
|
// suixinkanTests
|
|
//
|
|
|
|
import XCTest
|
|
@testable import suixinkan
|
|
|
|
/// 首页在线状态存储测试。
|
|
final class HomeLocationStateStoreTests: XCTestCase {
|
|
|
|
private var appStore: AppStore!
|
|
private var defaults: UserDefaults!
|
|
|
|
override func setUp() {
|
|
defaults = UserDefaults(suiteName: "HomeLocationStateStoreTests")!
|
|
defaults.removePersistentDomain(forName: "HomeLocationStateStoreTests")
|
|
appStore = AppStore(defaults: defaults)
|
|
appStore.session.userId = "1001"
|
|
appStore.session.accountType = .scenicUser
|
|
}
|
|
|
|
override func tearDown() {
|
|
appStore.logout()
|
|
super.tearDown()
|
|
}
|
|
|
|
func testExpiredOnlineSessionIsClearedOnRestore() {
|
|
let expiredTimestamp = Int64(Date().timeIntervalSince1970 * 1000) - HomeLocationStateStore.onlineDurationMillis - 1_000
|
|
appStore.location.onlineStatus = true
|
|
appStore.location.lastReportTime = expiredTimestamp
|
|
|
|
let stateStore = HomeLocationStateStore(store: appStore)
|
|
stateStore.restoreStateIfNeeded()
|
|
|
|
XCTAssertFalse(stateStore.isOnline)
|
|
XCTAssertFalse(appStore.location.onlineStatus)
|
|
XCTAssertEqual(appStore.location.lastReportTime, 0)
|
|
}
|
|
|
|
func testActiveOnlineSessionRestoresCountdown() {
|
|
let recentTimestamp = Int64(Date().timeIntervalSince1970 * 1000) - 60_000
|
|
appStore.location.onlineStatus = true
|
|
appStore.location.lastReportTime = recentTimestamp
|
|
|
|
let stateStore = HomeLocationStateStore(store: appStore)
|
|
stateStore.restoreStateIfNeeded()
|
|
|
|
XCTAssertTrue(stateStore.isOnline)
|
|
XCTAssertGreaterThan(stateStore.nextReportCountdownSeconds, 0)
|
|
}
|
|
|
|
func testFormattedCountdownText() {
|
|
let stateStore = HomeLocationStateStore(store: appStore)
|
|
XCTAssertEqual(stateStore.formattedCountdown(from: 3661), "01:01:01")
|
|
}
|
|
|
|
func testShouldTriggerTimeoutReminderWithinWindow() {
|
|
appStore.location.reminderMinutes = 10
|
|
let stateStore = HomeLocationStateStore(store: appStore)
|
|
stateStore.startLocationReport(at: Int64(Date().timeIntervalSince1970 * 1000))
|
|
stateStore.updateReminderMinutes(10)
|
|
// Force countdown into reminder window via reflection of internal state is not available;
|
|
// verify helper with manual expectation on threshold logic.
|
|
XCTAssertFalse(stateStore.shouldTriggerTimeoutReminder())
|
|
}
|
|
|
|
func testMultipleObserversReceiveStateChanges() {
|
|
let stateStore = HomeLocationStateStore(store: appStore)
|
|
let firstOwner = StateObserverOwner()
|
|
let secondOwner = StateObserverOwner()
|
|
var firstChangeCount = 0
|
|
var secondChangeCount = 0
|
|
|
|
stateStore.observe(firstOwner) { firstChangeCount += 1 }
|
|
stateStore.observe(secondOwner) { secondChangeCount += 1 }
|
|
stateStore.updateReminderMinutes(5)
|
|
|
|
XCTAssertEqual(firstChangeCount, 1)
|
|
XCTAssertEqual(secondChangeCount, 1)
|
|
|
|
stateStore.removeObserver(firstOwner)
|
|
stateStore.updateReminderMinutes(10)
|
|
|
|
XCTAssertEqual(firstChangeCount, 1)
|
|
XCTAssertEqual(secondChangeCount, 2)
|
|
}
|
|
|
|
func testViewModelsShareReminderMinutesWhenUsingSameStateStore() {
|
|
let stateStore = HomeLocationStateStore(store: appStore)
|
|
let homeViewModel = HomeViewModel(appStore: appStore, locationStateStore: stateStore)
|
|
let reportViewModel = LocationReportViewModel(
|
|
locationStateStore: stateStore,
|
|
locationProvider: MockLocationProvider()
|
|
)
|
|
|
|
homeViewModel.updateReminderMinutes(15)
|
|
|
|
XCTAssertEqual(reportViewModel.reminderMinutes, 15)
|
|
|
|
reportViewModel.updateReminderMinutes(5)
|
|
|
|
XCTAssertEqual(homeViewModel.reminderMinutes, 5)
|
|
}
|
|
|
|
func testViewModelsShareOnlineStateWhenUsingSameStateStore() {
|
|
let stateStore = HomeLocationStateStore(store: appStore)
|
|
let homeViewModel = HomeViewModel(appStore: appStore, locationStateStore: stateStore)
|
|
let reportViewModel = LocationReportViewModel(
|
|
locationStateStore: stateStore,
|
|
locationProvider: MockLocationProvider()
|
|
)
|
|
|
|
stateStore.startLocationReport(at: Int64(Date().timeIntervalSince1970 * 1000))
|
|
|
|
XCTAssertTrue(homeViewModel.isOnline)
|
|
XCTAssertTrue(reportViewModel.isOnline)
|
|
XCTAssertGreaterThan(stateStore.nextReportCountdownSeconds, 0)
|
|
|
|
stateStore.updateOnlineStatus(false)
|
|
|
|
XCTAssertFalse(homeViewModel.isOnline)
|
|
XCTAssertFalse(reportViewModel.isOnline)
|
|
}
|
|
|
|
func testRestoreClearsOnlineStateWhenStoredLastReportTimeIsMissing() {
|
|
appStore.location.onlineStatus = true
|
|
appStore.location.lastReportTime = 0
|
|
|
|
let stateStore = HomeLocationStateStore(store: appStore)
|
|
stateStore.restoreStateIfNeeded()
|
|
|
|
XCTAssertFalse(stateStore.isOnline)
|
|
XCTAssertFalse(appStore.location.onlineStatus)
|
|
XCTAssertEqual(appStore.location.lastReportTime, 0)
|
|
XCTAssertEqual(stateStore.nextReportCountdownSeconds, 0)
|
|
}
|
|
|
|
func testRestoreClearsRuntimeStateWhenPersistedOffline() {
|
|
let stateStore = HomeLocationStateStore(store: appStore)
|
|
stateStore.startLocationReport(at: Int64(Date().timeIntervalSince1970 * 1000))
|
|
appStore.location.onlineStatus = false
|
|
|
|
stateStore.restoreStateIfNeeded()
|
|
|
|
XCTAssertFalse(stateStore.isOnline)
|
|
XCTAssertEqual(stateStore.nextReportCountdownSeconds, 0)
|
|
}
|
|
}
|
|
|
|
private final class StateObserverOwner {}
|