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.userId = "1001"
|
|
appStore.accountType = "scenic_user"
|
|
}
|
|
|
|
override func tearDown() {
|
|
appStore.logout()
|
|
super.tearDown()
|
|
}
|
|
|
|
func testExpiredOnlineSessionIsClearedOnRestore() {
|
|
let expiredTimestamp = Int64(Date().timeIntervalSince1970 * 1000) - HomeLocationStateStore.onlineDurationMillis - 1_000
|
|
appStore.onlineStatus = true
|
|
appStore.lastLocationReportTime = expiredTimestamp
|
|
|
|
let stateStore = HomeLocationStateStore(store: appStore)
|
|
stateStore.restoreStateIfNeeded()
|
|
|
|
XCTAssertFalse(stateStore.isOnline)
|
|
XCTAssertFalse(appStore.onlineStatus)
|
|
XCTAssertEqual(appStore.lastLocationReportTime, 0)
|
|
}
|
|
|
|
func testActiveOnlineSessionRestoresCountdown() {
|
|
let recentTimestamp = Int64(Date().timeIntervalSince1970 * 1000) - 60_000
|
|
appStore.onlineStatus = true
|
|
appStore.lastLocationReportTime = 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.locationReminderMinutes = 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.onlineStatus = true
|
|
appStore.lastLocationReportTime = 0
|
|
|
|
let stateStore = HomeLocationStateStore(store: appStore)
|
|
stateStore.restoreStateIfNeeded()
|
|
|
|
XCTAssertFalse(stateStore.isOnline)
|
|
XCTAssertFalse(appStore.onlineStatus)
|
|
XCTAssertEqual(appStore.lastLocationReportTime, 0)
|
|
XCTAssertEqual(stateStore.nextReportCountdownSeconds, 0)
|
|
}
|
|
|
|
func testRestoreClearsRuntimeStateWhenPersistedOffline() {
|
|
let stateStore = HomeLocationStateStore(store: appStore)
|
|
stateStore.startLocationReport(at: Int64(Date().timeIntervalSince1970 * 1000))
|
|
appStore.onlineStatus = false
|
|
|
|
stateStore.restoreStateIfNeeded()
|
|
|
|
XCTAssertFalse(stateStore.isOnline)
|
|
XCTAssertEqual(stateStore.nextReportCountdownSeconds, 0)
|
|
}
|
|
}
|
|
|
|
private final class StateObserverOwner {}
|