feat: add lottie for animations
This commit is contained in:
53
GazeTests/Models/AnimationAssetTests.swift
Normal file
53
GazeTests/Models/AnimationAssetTests.swift
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// AnimationAssetTests.swift
|
||||
// GazeTests
|
||||
//
|
||||
// Created by Mike Freno on 1/8/26.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import Gaze
|
||||
|
||||
final class AnimationAssetTests: XCTestCase {
|
||||
|
||||
func testRawValues() {
|
||||
XCTAssertEqual(AnimationAsset.blink.rawValue, "blink")
|
||||
XCTAssertEqual(AnimationAsset.lookAway.rawValue, "look-away")
|
||||
XCTAssertEqual(AnimationAsset.posture.rawValue, "posture")
|
||||
}
|
||||
|
||||
func testFileNames() {
|
||||
XCTAssertEqual(AnimationAsset.blink.fileName, "blink")
|
||||
XCTAssertEqual(AnimationAsset.lookAway.fileName, "look-away")
|
||||
XCTAssertEqual(AnimationAsset.posture.fileName, "posture")
|
||||
}
|
||||
|
||||
func testFileNameMatchesRawValue() {
|
||||
XCTAssertEqual(AnimationAsset.blink.fileName, AnimationAsset.blink.rawValue)
|
||||
XCTAssertEqual(AnimationAsset.lookAway.fileName, AnimationAsset.lookAway.rawValue)
|
||||
XCTAssertEqual(AnimationAsset.posture.fileName, AnimationAsset.posture.rawValue)
|
||||
}
|
||||
|
||||
func testInitFromRawValue() {
|
||||
XCTAssertEqual(AnimationAsset(rawValue: "blink"), .blink)
|
||||
XCTAssertEqual(AnimationAsset(rawValue: "look-away"), .lookAway)
|
||||
XCTAssertEqual(AnimationAsset(rawValue: "posture"), .posture)
|
||||
XCTAssertNil(AnimationAsset(rawValue: "invalid"))
|
||||
}
|
||||
|
||||
func testEquality() {
|
||||
XCTAssertEqual(AnimationAsset.blink, AnimationAsset.blink)
|
||||
XCTAssertNotEqual(AnimationAsset.blink, AnimationAsset.lookAway)
|
||||
XCTAssertNotEqual(AnimationAsset.lookAway, AnimationAsset.posture)
|
||||
}
|
||||
|
||||
func testAllCasesExist() {
|
||||
let blink = AnimationAsset.blink
|
||||
let lookAway = AnimationAsset.lookAway
|
||||
let posture = AnimationAsset.posture
|
||||
|
||||
XCTAssertNotNil(blink)
|
||||
XCTAssertNotNil(lookAway)
|
||||
XCTAssertNotNil(posture)
|
||||
}
|
||||
}
|
||||
175
GazeTests/Models/AppSettingsTests.swift
Normal file
175
GazeTests/Models/AppSettingsTests.swift
Normal file
@@ -0,0 +1,175 @@
|
||||
//
|
||||
// AppSettingsTests.swift
|
||||
// GazeTests
|
||||
//
|
||||
// Created by Mike Freno on 1/8/26.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import Gaze
|
||||
|
||||
final class AppSettingsTests: XCTestCase {
|
||||
|
||||
func testDefaultSettings() {
|
||||
let settings = AppSettings.defaults
|
||||
|
||||
XCTAssertTrue(settings.lookAwayTimer.enabled)
|
||||
XCTAssertEqual(settings.lookAwayTimer.intervalSeconds, 20 * 60)
|
||||
XCTAssertEqual(settings.lookAwayCountdownSeconds, 20)
|
||||
|
||||
XCTAssertTrue(settings.blinkTimer.enabled)
|
||||
XCTAssertEqual(settings.blinkTimer.intervalSeconds, 5 * 60)
|
||||
|
||||
XCTAssertTrue(settings.postureTimer.enabled)
|
||||
XCTAssertEqual(settings.postureTimer.intervalSeconds, 30 * 60)
|
||||
|
||||
XCTAssertFalse(settings.hasCompletedOnboarding)
|
||||
XCTAssertFalse(settings.launchAtLogin)
|
||||
XCTAssertTrue(settings.playSounds)
|
||||
}
|
||||
|
||||
func testEquality() {
|
||||
let settings1 = AppSettings.defaults
|
||||
let settings2 = AppSettings.defaults
|
||||
|
||||
XCTAssertEqual(settings1, settings2)
|
||||
}
|
||||
|
||||
func testInequalityWhenLookAwayTimerDiffers() {
|
||||
var settings1 = AppSettings.defaults
|
||||
var settings2 = AppSettings.defaults
|
||||
|
||||
settings2.lookAwayTimer.enabled = false
|
||||
XCTAssertNotEqual(settings1, settings2)
|
||||
|
||||
settings2.lookAwayTimer.enabled = true
|
||||
settings2.lookAwayTimer.intervalSeconds = 10 * 60
|
||||
XCTAssertNotEqual(settings1, settings2)
|
||||
}
|
||||
|
||||
func testInequalityWhenCountdownDiffers() {
|
||||
var settings1 = AppSettings.defaults
|
||||
var settings2 = AppSettings.defaults
|
||||
|
||||
settings2.lookAwayCountdownSeconds = 30
|
||||
XCTAssertNotEqual(settings1, settings2)
|
||||
}
|
||||
|
||||
func testInequalityWhenBlinkTimerDiffers() {
|
||||
var settings1 = AppSettings.defaults
|
||||
var settings2 = AppSettings.defaults
|
||||
|
||||
settings2.blinkTimer.enabled = false
|
||||
XCTAssertNotEqual(settings1, settings2)
|
||||
}
|
||||
|
||||
func testInequalityWhenPostureTimerDiffers() {
|
||||
var settings1 = AppSettings.defaults
|
||||
var settings2 = AppSettings.defaults
|
||||
|
||||
settings2.postureTimer.intervalSeconds = 60 * 60
|
||||
XCTAssertNotEqual(settings1, settings2)
|
||||
}
|
||||
|
||||
func testInequalityWhenOnboardingDiffers() {
|
||||
var settings1 = AppSettings.defaults
|
||||
var settings2 = AppSettings.defaults
|
||||
|
||||
settings2.hasCompletedOnboarding = true
|
||||
XCTAssertNotEqual(settings1, settings2)
|
||||
}
|
||||
|
||||
func testInequalityWhenLaunchAtLoginDiffers() {
|
||||
var settings1 = AppSettings.defaults
|
||||
var settings2 = AppSettings.defaults
|
||||
|
||||
settings2.launchAtLogin = true
|
||||
XCTAssertNotEqual(settings1, settings2)
|
||||
}
|
||||
|
||||
func testInequalityWhenPlaySoundsDiffers() {
|
||||
var settings1 = AppSettings.defaults
|
||||
var settings2 = AppSettings.defaults
|
||||
|
||||
settings2.playSounds = false
|
||||
XCTAssertNotEqual(settings1, settings2)
|
||||
}
|
||||
|
||||
func testCodableEncoding() throws {
|
||||
let settings = AppSettings.defaults
|
||||
let encoder = JSONEncoder()
|
||||
let data = try encoder.encode(settings)
|
||||
|
||||
XCTAssertNotNil(data)
|
||||
XCTAssertGreaterThan(data.count, 0)
|
||||
}
|
||||
|
||||
func testCodableDecoding() throws {
|
||||
let settings = AppSettings.defaults
|
||||
let encoder = JSONEncoder()
|
||||
let data = try encoder.encode(settings)
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(AppSettings.self, from: data)
|
||||
|
||||
XCTAssertEqual(decoded, settings)
|
||||
}
|
||||
|
||||
func testCodableRoundTripWithModifiedSettings() throws {
|
||||
var settings = AppSettings.defaults
|
||||
settings.lookAwayTimer.enabled = false
|
||||
settings.lookAwayCountdownSeconds = 30
|
||||
settings.blinkTimer.intervalSeconds = 10 * 60
|
||||
settings.postureTimer.enabled = false
|
||||
settings.hasCompletedOnboarding = true
|
||||
settings.launchAtLogin = true
|
||||
settings.playSounds = false
|
||||
|
||||
let encoder = JSONEncoder()
|
||||
let data = try encoder.encode(settings)
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(AppSettings.self, from: data)
|
||||
|
||||
XCTAssertEqual(decoded, settings)
|
||||
XCTAssertFalse(decoded.lookAwayTimer.enabled)
|
||||
XCTAssertEqual(decoded.lookAwayCountdownSeconds, 30)
|
||||
XCTAssertEqual(decoded.blinkTimer.intervalSeconds, 10 * 60)
|
||||
XCTAssertFalse(decoded.postureTimer.enabled)
|
||||
XCTAssertTrue(decoded.hasCompletedOnboarding)
|
||||
XCTAssertTrue(decoded.launchAtLogin)
|
||||
XCTAssertFalse(decoded.playSounds)
|
||||
}
|
||||
|
||||
func testMutability() {
|
||||
var settings = AppSettings.defaults
|
||||
|
||||
settings.lookAwayTimer.enabled = false
|
||||
XCTAssertFalse(settings.lookAwayTimer.enabled)
|
||||
|
||||
settings.lookAwayCountdownSeconds = 30
|
||||
XCTAssertEqual(settings.lookAwayCountdownSeconds, 30)
|
||||
|
||||
settings.hasCompletedOnboarding = true
|
||||
XCTAssertTrue(settings.hasCompletedOnboarding)
|
||||
|
||||
settings.launchAtLogin = true
|
||||
XCTAssertTrue(settings.launchAtLogin)
|
||||
|
||||
settings.playSounds = false
|
||||
XCTAssertFalse(settings.playSounds)
|
||||
}
|
||||
|
||||
func testBoundaryValues() {
|
||||
var settings = AppSettings.defaults
|
||||
|
||||
settings.lookAwayTimer.intervalSeconds = 0
|
||||
XCTAssertEqual(settings.lookAwayTimer.intervalSeconds, 0)
|
||||
|
||||
settings.lookAwayCountdownSeconds = 0
|
||||
XCTAssertEqual(settings.lookAwayCountdownSeconds, 0)
|
||||
|
||||
settings.lookAwayTimer.intervalSeconds = Int.max
|
||||
XCTAssertEqual(settings.lookAwayTimer.intervalSeconds, Int.max)
|
||||
}
|
||||
}
|
||||
115
GazeTests/Models/ReminderEventTests.swift
Normal file
115
GazeTests/Models/ReminderEventTests.swift
Normal file
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// ReminderEventTests.swift
|
||||
// GazeTests
|
||||
//
|
||||
// Created by Mike Freno on 1/8/26.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import Gaze
|
||||
|
||||
final class ReminderEventTests: XCTestCase {
|
||||
|
||||
func testLookAwayTriggeredCreation() {
|
||||
let event = ReminderEvent.lookAwayTriggered(countdownSeconds: 20)
|
||||
|
||||
if case .lookAwayTriggered(let countdown) = event {
|
||||
XCTAssertEqual(countdown, 20)
|
||||
} else {
|
||||
XCTFail("Expected lookAwayTriggered event")
|
||||
}
|
||||
}
|
||||
|
||||
func testBlinkTriggeredCreation() {
|
||||
let event = ReminderEvent.blinkTriggered
|
||||
|
||||
if case .blinkTriggered = event {
|
||||
XCTAssertTrue(true)
|
||||
} else {
|
||||
XCTFail("Expected blinkTriggered event")
|
||||
}
|
||||
}
|
||||
|
||||
func testPostureTriggeredCreation() {
|
||||
let event = ReminderEvent.postureTriggered
|
||||
|
||||
if case .postureTriggered = event {
|
||||
XCTAssertTrue(true)
|
||||
} else {
|
||||
XCTFail("Expected postureTriggered event")
|
||||
}
|
||||
}
|
||||
|
||||
func testTypePropertyForLookAway() {
|
||||
let event = ReminderEvent.lookAwayTriggered(countdownSeconds: 20)
|
||||
XCTAssertEqual(event.type, .lookAway)
|
||||
}
|
||||
|
||||
func testTypePropertyForBlink() {
|
||||
let event = ReminderEvent.blinkTriggered
|
||||
XCTAssertEqual(event.type, .blink)
|
||||
}
|
||||
|
||||
func testTypePropertyForPosture() {
|
||||
let event = ReminderEvent.postureTriggered
|
||||
XCTAssertEqual(event.type, .posture)
|
||||
}
|
||||
|
||||
func testEquality() {
|
||||
let event1 = ReminderEvent.lookAwayTriggered(countdownSeconds: 20)
|
||||
let event2 = ReminderEvent.lookAwayTriggered(countdownSeconds: 20)
|
||||
let event3 = ReminderEvent.lookAwayTriggered(countdownSeconds: 30)
|
||||
let event4 = ReminderEvent.blinkTriggered
|
||||
let event5 = ReminderEvent.blinkTriggered
|
||||
let event6 = ReminderEvent.postureTriggered
|
||||
|
||||
XCTAssertEqual(event1, event2)
|
||||
XCTAssertNotEqual(event1, event3)
|
||||
XCTAssertNotEqual(event1, event4)
|
||||
XCTAssertEqual(event4, event5)
|
||||
XCTAssertNotEqual(event4, event6)
|
||||
}
|
||||
|
||||
func testDifferentCountdownValues() {
|
||||
let event1 = ReminderEvent.lookAwayTriggered(countdownSeconds: 0)
|
||||
let event2 = ReminderEvent.lookAwayTriggered(countdownSeconds: 10)
|
||||
let event3 = ReminderEvent.lookAwayTriggered(countdownSeconds: 60)
|
||||
|
||||
XCTAssertNotEqual(event1, event2)
|
||||
XCTAssertNotEqual(event2, event3)
|
||||
XCTAssertNotEqual(event1, event3)
|
||||
|
||||
XCTAssertEqual(event1.type, .lookAway)
|
||||
XCTAssertEqual(event2.type, .lookAway)
|
||||
XCTAssertEqual(event3.type, .lookAway)
|
||||
}
|
||||
|
||||
func testNegativeCountdown() {
|
||||
let event = ReminderEvent.lookAwayTriggered(countdownSeconds: -5)
|
||||
|
||||
if case .lookAwayTriggered(let countdown) = event {
|
||||
XCTAssertEqual(countdown, -5)
|
||||
} else {
|
||||
XCTFail("Expected lookAwayTriggered event")
|
||||
}
|
||||
}
|
||||
|
||||
func testSwitchExhaustivenessWithAllCases() {
|
||||
let events: [ReminderEvent] = [
|
||||
.lookAwayTriggered(countdownSeconds: 20),
|
||||
.blinkTriggered,
|
||||
.postureTriggered
|
||||
]
|
||||
|
||||
for event in events {
|
||||
switch event {
|
||||
case .lookAwayTriggered:
|
||||
XCTAssertEqual(event.type, .lookAway)
|
||||
case .blinkTriggered:
|
||||
XCTAssertEqual(event.type, .blink)
|
||||
case .postureTriggered:
|
||||
XCTAssertEqual(event.type, .posture)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
124
GazeTests/Models/TimerConfigurationTests.swift
Normal file
124
GazeTests/Models/TimerConfigurationTests.swift
Normal file
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// TimerConfigurationTests.swift
|
||||
// GazeTests
|
||||
//
|
||||
// Created by Mike Freno on 1/8/26.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import Gaze
|
||||
|
||||
final class TimerConfigurationTests: XCTestCase {
|
||||
|
||||
func testInitialization() {
|
||||
let config = TimerConfiguration(enabled: true, intervalSeconds: 1200)
|
||||
|
||||
XCTAssertTrue(config.enabled)
|
||||
XCTAssertEqual(config.intervalSeconds, 1200)
|
||||
}
|
||||
|
||||
func testInitializationDisabled() {
|
||||
let config = TimerConfiguration(enabled: false, intervalSeconds: 600)
|
||||
|
||||
XCTAssertFalse(config.enabled)
|
||||
XCTAssertEqual(config.intervalSeconds, 600)
|
||||
}
|
||||
|
||||
func testIntervalMinutesGetter() {
|
||||
let config = TimerConfiguration(enabled: true, intervalSeconds: 1200)
|
||||
XCTAssertEqual(config.intervalMinutes, 20)
|
||||
}
|
||||
|
||||
func testIntervalMinutesSetter() {
|
||||
var config = TimerConfiguration(enabled: true, intervalSeconds: 0)
|
||||
config.intervalMinutes = 15
|
||||
|
||||
XCTAssertEqual(config.intervalMinutes, 15)
|
||||
XCTAssertEqual(config.intervalSeconds, 900)
|
||||
}
|
||||
|
||||
func testIntervalMinutesConversion() {
|
||||
var config = TimerConfiguration(enabled: true, intervalSeconds: 0)
|
||||
|
||||
config.intervalMinutes = 1
|
||||
XCTAssertEqual(config.intervalSeconds, 60)
|
||||
|
||||
config.intervalMinutes = 60
|
||||
XCTAssertEqual(config.intervalSeconds, 3600)
|
||||
|
||||
config.intervalMinutes = 0
|
||||
XCTAssertEqual(config.intervalSeconds, 0)
|
||||
}
|
||||
|
||||
func testEquality() {
|
||||
let config1 = TimerConfiguration(enabled: true, intervalSeconds: 1200)
|
||||
let config2 = TimerConfiguration(enabled: true, intervalSeconds: 1200)
|
||||
let config3 = TimerConfiguration(enabled: false, intervalSeconds: 1200)
|
||||
let config4 = TimerConfiguration(enabled: true, intervalSeconds: 600)
|
||||
|
||||
XCTAssertEqual(config1, config2)
|
||||
XCTAssertNotEqual(config1, config3)
|
||||
XCTAssertNotEqual(config1, config4)
|
||||
}
|
||||
|
||||
func testCodableEncoding() throws {
|
||||
let config = TimerConfiguration(enabled: true, intervalSeconds: 1200)
|
||||
let encoder = JSONEncoder()
|
||||
let data = try encoder.encode(config)
|
||||
|
||||
XCTAssertNotNil(data)
|
||||
XCTAssertGreaterThan(data.count, 0)
|
||||
}
|
||||
|
||||
func testCodableDecoding() throws {
|
||||
let config = TimerConfiguration(enabled: true, intervalSeconds: 1200)
|
||||
let encoder = JSONEncoder()
|
||||
let data = try encoder.encode(config)
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(TimerConfiguration.self, from: data)
|
||||
|
||||
XCTAssertEqual(decoded, config)
|
||||
}
|
||||
|
||||
func testCodableRoundTrip() throws {
|
||||
let configs = [
|
||||
TimerConfiguration(enabled: true, intervalSeconds: 300),
|
||||
TimerConfiguration(enabled: false, intervalSeconds: 1200),
|
||||
TimerConfiguration(enabled: true, intervalSeconds: 1800),
|
||||
TimerConfiguration(enabled: false, intervalSeconds: 0)
|
||||
]
|
||||
|
||||
let encoder = JSONEncoder()
|
||||
let decoder = JSONDecoder()
|
||||
|
||||
for config in configs {
|
||||
let data = try encoder.encode(config)
|
||||
let decoded = try decoder.decode(TimerConfiguration.self, from: data)
|
||||
XCTAssertEqual(decoded, config)
|
||||
}
|
||||
}
|
||||
|
||||
func testMutability() {
|
||||
var config = TimerConfiguration(enabled: true, intervalSeconds: 1200)
|
||||
|
||||
config.enabled = false
|
||||
XCTAssertFalse(config.enabled)
|
||||
|
||||
config.intervalSeconds = 600
|
||||
XCTAssertEqual(config.intervalSeconds, 600)
|
||||
XCTAssertEqual(config.intervalMinutes, 10)
|
||||
}
|
||||
|
||||
func testZeroInterval() {
|
||||
let config = TimerConfiguration(enabled: true, intervalSeconds: 0)
|
||||
XCTAssertEqual(config.intervalSeconds, 0)
|
||||
XCTAssertEqual(config.intervalMinutes, 0)
|
||||
}
|
||||
|
||||
func testLargeInterval() {
|
||||
let config = TimerConfiguration(enabled: true, intervalSeconds: 86400)
|
||||
XCTAssertEqual(config.intervalSeconds, 86400)
|
||||
XCTAssertEqual(config.intervalMinutes, 1440)
|
||||
}
|
||||
}
|
||||
93
GazeTests/Models/TimerStateTests.swift
Normal file
93
GazeTests/Models/TimerStateTests.swift
Normal file
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// TimerStateTests.swift
|
||||
// GazeTests
|
||||
//
|
||||
// Created by Mike Freno on 1/8/26.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import Gaze
|
||||
|
||||
final class TimerStateTests: XCTestCase {
|
||||
|
||||
func testInitialization() {
|
||||
let state = TimerState(type: .lookAway, intervalSeconds: 1200)
|
||||
|
||||
XCTAssertEqual(state.type, .lookAway)
|
||||
XCTAssertEqual(state.remainingSeconds, 1200)
|
||||
XCTAssertFalse(state.isPaused)
|
||||
XCTAssertTrue(state.isActive)
|
||||
}
|
||||
|
||||
func testInitializationWithPausedState() {
|
||||
let state = TimerState(type: .blink, intervalSeconds: 300, isPaused: true)
|
||||
|
||||
XCTAssertEqual(state.type, .blink)
|
||||
XCTAssertEqual(state.remainingSeconds, 300)
|
||||
XCTAssertTrue(state.isPaused)
|
||||
XCTAssertTrue(state.isActive)
|
||||
}
|
||||
|
||||
func testInitializationWithInactiveState() {
|
||||
let state = TimerState(type: .posture, intervalSeconds: 1800, isPaused: false, isActive: false)
|
||||
|
||||
XCTAssertEqual(state.type, .posture)
|
||||
XCTAssertEqual(state.remainingSeconds, 1800)
|
||||
XCTAssertFalse(state.isPaused)
|
||||
XCTAssertFalse(state.isActive)
|
||||
}
|
||||
|
||||
func testMutability() {
|
||||
var state = TimerState(type: .lookAway, intervalSeconds: 1200)
|
||||
|
||||
state.remainingSeconds = 600
|
||||
XCTAssertEqual(state.remainingSeconds, 600)
|
||||
|
||||
state.isPaused = true
|
||||
XCTAssertTrue(state.isPaused)
|
||||
|
||||
state.isActive = false
|
||||
XCTAssertFalse(state.isActive)
|
||||
}
|
||||
|
||||
func testEquality() {
|
||||
let state1 = TimerState(type: .lookAway, intervalSeconds: 1200)
|
||||
let state2 = TimerState(type: .lookAway, intervalSeconds: 1200)
|
||||
let state3 = TimerState(type: .blink, intervalSeconds: 1200)
|
||||
let state4 = TimerState(type: .lookAway, intervalSeconds: 600)
|
||||
|
||||
XCTAssertEqual(state1, state2)
|
||||
XCTAssertNotEqual(state1, state3)
|
||||
XCTAssertNotEqual(state1, state4)
|
||||
}
|
||||
|
||||
func testEqualityWithDifferentPausedState() {
|
||||
let state1 = TimerState(type: .lookAway, intervalSeconds: 1200, isPaused: false)
|
||||
let state2 = TimerState(type: .lookAway, intervalSeconds: 1200, isPaused: true)
|
||||
|
||||
XCTAssertNotEqual(state1, state2)
|
||||
}
|
||||
|
||||
func testEqualityWithDifferentActiveState() {
|
||||
let state1 = TimerState(type: .lookAway, intervalSeconds: 1200, isActive: true)
|
||||
let state2 = TimerState(type: .lookAway, intervalSeconds: 1200, isActive: false)
|
||||
|
||||
XCTAssertNotEqual(state1, state2)
|
||||
}
|
||||
|
||||
func testZeroRemainingSeconds() {
|
||||
let state = TimerState(type: .lookAway, intervalSeconds: 0)
|
||||
XCTAssertEqual(state.remainingSeconds, 0)
|
||||
}
|
||||
|
||||
func testNegativeRemainingSeconds() {
|
||||
var state = TimerState(type: .lookAway, intervalSeconds: 10)
|
||||
state.remainingSeconds = -5
|
||||
XCTAssertEqual(state.remainingSeconds, -5)
|
||||
}
|
||||
|
||||
func testLargeIntervalSeconds() {
|
||||
let state = TimerState(type: .posture, intervalSeconds: 86400)
|
||||
XCTAssertEqual(state.remainingSeconds, 86400)
|
||||
}
|
||||
}
|
||||
68
GazeTests/Models/TimerTypeTests.swift
Normal file
68
GazeTests/Models/TimerTypeTests.swift
Normal file
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// TimerTypeTests.swift
|
||||
// GazeTests
|
||||
//
|
||||
// Created by Mike Freno on 1/8/26.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import Gaze
|
||||
|
||||
final class TimerTypeTests: XCTestCase {
|
||||
|
||||
func testAllCases() {
|
||||
let allCases = TimerType.allCases
|
||||
XCTAssertEqual(allCases.count, 3)
|
||||
XCTAssertTrue(allCases.contains(.lookAway))
|
||||
XCTAssertTrue(allCases.contains(.blink))
|
||||
XCTAssertTrue(allCases.contains(.posture))
|
||||
}
|
||||
|
||||
func testRawValues() {
|
||||
XCTAssertEqual(TimerType.lookAway.rawValue, "lookAway")
|
||||
XCTAssertEqual(TimerType.blink.rawValue, "blink")
|
||||
XCTAssertEqual(TimerType.posture.rawValue, "posture")
|
||||
}
|
||||
|
||||
func testDisplayNames() {
|
||||
XCTAssertEqual(TimerType.lookAway.displayName, "Look Away")
|
||||
XCTAssertEqual(TimerType.blink.displayName, "Blink")
|
||||
XCTAssertEqual(TimerType.posture.displayName, "Posture")
|
||||
}
|
||||
|
||||
func testIconNames() {
|
||||
XCTAssertEqual(TimerType.lookAway.iconName, "eye.fill")
|
||||
XCTAssertEqual(TimerType.blink.iconName, "eye.circle")
|
||||
XCTAssertEqual(TimerType.posture.iconName, "figure.stand")
|
||||
}
|
||||
|
||||
func testIdentifiable() {
|
||||
XCTAssertEqual(TimerType.lookAway.id, "lookAway")
|
||||
XCTAssertEqual(TimerType.blink.id, "blink")
|
||||
XCTAssertEqual(TimerType.posture.id, "posture")
|
||||
}
|
||||
|
||||
func testCodable() throws {
|
||||
let encoder = JSONEncoder()
|
||||
let decoder = JSONDecoder()
|
||||
|
||||
for timerType in TimerType.allCases {
|
||||
let encoded = try encoder.encode(timerType)
|
||||
let decoded = try decoder.decode(TimerType.self, from: encoded)
|
||||
XCTAssertEqual(decoded, timerType)
|
||||
}
|
||||
}
|
||||
|
||||
func testEquality() {
|
||||
XCTAssertEqual(TimerType.lookAway, TimerType.lookAway)
|
||||
XCTAssertNotEqual(TimerType.lookAway, TimerType.blink)
|
||||
XCTAssertNotEqual(TimerType.blink, TimerType.posture)
|
||||
}
|
||||
|
||||
func testInitFromRawValue() {
|
||||
XCTAssertEqual(TimerType(rawValue: "lookAway"), .lookAway)
|
||||
XCTAssertEqual(TimerType(rawValue: "blink"), .blink)
|
||||
XCTAssertEqual(TimerType(rawValue: "posture"), .posture)
|
||||
XCTAssertNil(TimerType(rawValue: "invalid"))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user