remindwall / RWPureSwift / Tests / AppNavigationTests / AppNavigationTests.swift
Back to remindwall — Current RemindWall
import AppTypes
import ComposableArchitecture
import DependenciesTestSupport
import Foundation
import Testing
@testable import AppNavigation
@testable import EditSettingsNew_TopLevel
@MainActor
@Suite("AppNavigation Feature Tests", .dependencies {
$0.defaultDatabase = try! $0.appDatabase()
$0.uuid = .incrementing
})
struct AppNavigationFeatureTests {
@Test("initial state is settings screen")
func initialState() async {
let state = AppNavigationFeature.State()
#expect(state.screen == .settings)
}
@Test("onAppear starts screen off monitoring")
func onAppearStartsMonitoring() async {
let clock = TestClock()
let store = TestStore(initialState: AppNavigationFeature.State()) {
AppNavigationFeature()
} withDependencies: {
$0.continuousClock = clock
$0.date = .constant(Date())
$0.calendar = .current
$0.screenControl.getBrightness = { 0.75 }
$0.screenControl.setBrightness = { _ in }
// onAppear starts the settings resolver; unauthorized access
// makes its initial reconcile a no-op.
$0.photoKitAlbums.libraryAccess = { .notDetermined }
$0.calendarAsync.calendarAccess = { .notDetermined }
}
store.exhaustivity = .off
await store.send(.onAppear)
await store.receive(\.screenOffMonitor.startMonitoring)
await store.finish()
}
@Test("onAppear with configured slideshow switches to dashboard")
func onAppearWithConfiguredSlideshow() async {
let clock = TestClock()
var state = AppNavigationFeature.State()
state.settingsState.albumPickerState.$selectedAlbum.withLock { $0 = AlbumLocalId("test-album") }
let store = TestStore(initialState: state) {
AppNavigationFeature()
} withDependencies: {
$0.continuousClock = clock
$0.date = .constant(Date())
$0.calendar = .current
$0.screenControl.getBrightness = { 0.75 }
$0.screenControl.setBrightness = { _ in }
// onAppear starts the settings resolver; unauthorized access
// makes its initial reconcile a no-op.
$0.photoKitAlbums.libraryAccess = { .notDetermined }
$0.calendarAsync.calendarAccess = { .notDetermined }
}
store.exhaustivity = .off
await store.send(.onAppear) {
$0.screen = .dashboard
$0.screenOffMonitorState.isSlideshowPlaying = true
}
await store.receive(\.screenOffMonitor.startMonitoring)
await store.finish()
}
@Test("onAppear without configured slideshow stays on settings")
func onAppearWithoutConfiguredSlideshow() async {
let clock = TestClock()
let store = TestStore(initialState: AppNavigationFeature.State()) {
AppNavigationFeature()
} withDependencies: {
$0.continuousClock = clock
$0.date = .constant(Date())
$0.calendar = .current
$0.screenControl.getBrightness = { 0.75 }
$0.screenControl.setBrightness = { _ in }
// onAppear starts the settings resolver; unauthorized access
// makes its initial reconcile a no-op.
$0.photoKitAlbums.libraryAccess = { .notDetermined }
$0.calendarAsync.calendarAccess = { .notDetermined }
}
store.exhaustivity = .off
await store.send(.onAppear)
await store.receive(\.screenOffMonitor.startMonitoring)
await store.finish()
}
@Test("startSlideshow delegate switches to dashboard")
func startSlideshowSwitchesToDashboard() async {
let store = TestStore(initialState: AppNavigationFeature.State()) {
AppNavigationFeature()
}
store.exhaustivity = .off
await store.send(.settings(.startSlideshow))
await store.receive(\.settings.delegate.startSlideshow) {
$0.screen = .dashboard
$0.screenOffMonitorState.isSlideshowPlaying = true
}
}
@Test("showDashboard switches screen to dashboard")
func showDashboard() async {
let store = TestStore(initialState: AppNavigationFeature.State()) {
AppNavigationFeature()
}
await store.send(.showDashboard) {
$0.screen = .dashboard
$0.screenOffMonitorState.isSlideshowPlaying = true
}
}
@Test("showSettings switches screen to settings")
func showSettings() async {
var state = AppNavigationFeature.State()
state.screen = .dashboard
state.screenOffMonitorState.isSlideshowPlaying = true
let store = TestStore(initialState: state) {
AppNavigationFeature()
}
await store.send(.showSettings) {
$0.screen = .settings
$0.screenOffMonitorState.isSlideshowPlaying = false
}
}
@Test("dashboard returnToSettings delegate switches to settings")
func dashboardReturnToSettings() async {
var state = AppNavigationFeature.State()
state.screen = .dashboard
state.screenOffMonitorState.isSlideshowPlaying = true
let store = TestStore(initialState: state) {
AppNavigationFeature()
}
store.exhaustivity = .off
await store.send(.dashboard(.delegate(.returnToSettings))) {
$0.screen = .settings
$0.screenOffMonitorState.isSlideshowPlaying = false
}
}
@Test("settings action is forwarded without side effects")
func settingsActionForwarded() async {
let store = TestStore(initialState: AppNavigationFeature.State()) {
AppNavigationFeature()
} withDependencies: {
$0.photoKitAlbums.libraryAccess = { .notDetermined }
}
await store.send(.settings(.albumPicker(.onAppear)))
}
@Test("startSlideshow sets isSlideshowPlaying on screen off monitor")
func startSlideshowSetsSlideshowPlaying() async {
let store = TestStore(initialState: AppNavigationFeature.State()) {
AppNavigationFeature()
}
store.exhaustivity = .off
await store.send(.settings(.startSlideshow))
await store.receive(\.settings.delegate.startSlideshow) {
$0.screen = .dashboard
$0.screenOffMonitorState.isSlideshowPlaying = true
}
}
@Test("returnToSettings clears isSlideshowPlaying on screen off monitor")
func returnToSettingsClearsSlideshowPlaying() async {
var state = AppNavigationFeature.State()
state.screen = .dashboard
state.screenOffMonitorState.isSlideshowPlaying = true
let store = TestStore(initialState: state) {
AppNavigationFeature()
}
store.exhaustivity = .off
await store.send(.dashboard(.delegate(.returnToSettings))) {
$0.screen = .settings
$0.screenOffMonitorState.isSlideshowPlaying = false
}
}
@Test("tick updates hasLateReminders on screen off monitor")
func lateTrackeesUpdatesHasLateReminders() async {
var state = AppNavigationFeature.State()
state.screen = .dashboard
let store = TestStore(initialState: state) {
AppNavigationFeature()
} withDependencies: {
$0.date = .constant(Date())
$0.calendar = .current
}
// With no late reminders, tick should set hasLateReminders to false
await store.send(.dashboard(.alertLoader(.tick))) {
$0.dashboardState.alertLoaderState.dayOfWeek = Calendar.current.weekdaySymbols[
Calendar.current.component(.weekday, from: Date()) - 1
]
}
}
@Test("screenOffMonitor action is forwarded without side effects")
func screenOffMonitorActionForwarded() async {
let clock = TestClock()
let store = TestStore(initialState: AppNavigationFeature.State()) {
AppNavigationFeature()
} withDependencies: {
$0.continuousClock = clock
$0.date = .constant(Date())
$0.calendar = .current
$0.screenControl.getBrightness = { 0.75 }
$0.screenControl.setBrightness = { _ in }
}
store.exhaustivity = .off
await store.send(.screenOffMonitor(.startMonitoring)) {
$0.screenOffMonitorState.isMonitoring = true
}
await store.finish()
}
}