mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Swift Testing for Unit Tests PART 1 (#5119)
* migrated a lot of unit tests to Swift Testing and added a new implementation for deferred fulfillment more tests migration Cleaned the code manually to establish some good patterns more code improvements some more code improvements removed empty tests update project * more pr suggestions and cleanups * removed the TestSetup pattern * fixing claude not reusing tests * pr suggestion + added indent rule to swiftformat so that we can prevent AIs to change that
This commit is contained in:
@@ -7,150 +7,155 @@
|
||||
//
|
||||
|
||||
@testable import ElementX
|
||||
import XCTest
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
class AppLockTimerTests: XCTestCase {
|
||||
var timer: AppLockTimer!
|
||||
|
||||
let now = Date.now
|
||||
@Suite
|
||||
struct AppLockTimerTests {
|
||||
private let now = Date.now
|
||||
private var timer: AppLockTimer!
|
||||
|
||||
var gracePeriod: TimeInterval {
|
||||
timer.gracePeriod
|
||||
}
|
||||
|
||||
|
||||
var halfGracePeriod: TimeInterval {
|
||||
gracePeriod / 2
|
||||
timer.gracePeriod / 2
|
||||
}
|
||||
|
||||
|
||||
var gracePeriodX2: TimeInterval {
|
||||
gracePeriod * 2
|
||||
timer.gracePeriod * 2
|
||||
}
|
||||
|
||||
|
||||
var gracePeriodX10: TimeInterval {
|
||||
gracePeriod * 10
|
||||
timer.gracePeriod * 10
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
timer = nil
|
||||
@Test
|
||||
mutating func timerLockedOnStartup() {
|
||||
setupTimer(unlocked: false)
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now),
|
||||
"The app should be locked on a fresh launch.")
|
||||
|
||||
setupTimer(unlocked: false)
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now + 1),
|
||||
"The app should be locked after a fresh launch.")
|
||||
|
||||
setupTimer(unlocked: false)
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now + halfGracePeriod),
|
||||
"The app should be locked after a fresh launch.")
|
||||
|
||||
setupTimer(unlocked: false)
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now + gracePeriod),
|
||||
"The app should be locked after a fresh launch.")
|
||||
|
||||
setupTimer(unlocked: false)
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now + gracePeriodX10),
|
||||
"The app should be locked after a fresh launch.")
|
||||
}
|
||||
|
||||
func testTimerLockedOnStartup() {
|
||||
setupTimer(unlocked: false)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now),
|
||||
"The app should be locked on a fresh launch.")
|
||||
@Test
|
||||
mutating func timerBeforeFirstUnlock() {
|
||||
setupTimer(unlocked: false, backgroundedAt: now)
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now),
|
||||
"The app should always remain locked after backgrounding when locked.")
|
||||
|
||||
setupTimer(unlocked: false)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now + 1),
|
||||
"The app should be locked after a fresh launch.")
|
||||
setupTimer(unlocked: false, backgroundedAt: now)
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now + 1),
|
||||
"The app should always remain locked after backgrounding when locked.")
|
||||
|
||||
setupTimer(unlocked: false)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now + halfGracePeriod),
|
||||
"The app should be locked after a fresh launch.")
|
||||
setupTimer(unlocked: false, backgroundedAt: now)
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now + halfGracePeriod),
|
||||
"The app should always remain locked after backgrounding when locked.")
|
||||
|
||||
setupTimer(unlocked: false)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now + gracePeriod),
|
||||
"The app should be locked after a fresh launch.")
|
||||
setupTimer(unlocked: false, backgroundedAt: now)
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now + gracePeriod),
|
||||
"The app should always remain locked after backgrounding when locked.")
|
||||
|
||||
setupTimer(unlocked: false)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now + gracePeriodX10),
|
||||
"The app should be locked after a fresh launch.")
|
||||
setupTimer(unlocked: false, backgroundedAt: now)
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now + gracePeriodX10),
|
||||
"The app should always remain locked after backgrounding when locked.")
|
||||
}
|
||||
|
||||
func testTimerBeforeFirstUnlock() {
|
||||
setupTimer(unlocked: false, backgroundedAt: now)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now),
|
||||
"The app should always remain locked after backgrounding when locked.")
|
||||
|
||||
setupTimer(unlocked: false, backgroundedAt: now)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now + 1),
|
||||
"The app should always remain locked after backgrounding when locked.")
|
||||
|
||||
setupTimer(unlocked: false, backgroundedAt: now)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now + halfGracePeriod),
|
||||
"The app should always remain locked after backgrounding when locked.")
|
||||
|
||||
setupTimer(unlocked: false, backgroundedAt: now)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now + gracePeriod),
|
||||
"The app should always remain locked after backgrounding when locked.")
|
||||
|
||||
setupTimer(unlocked: false, backgroundedAt: now)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now + gracePeriodX10),
|
||||
"The app should always remain locked after backgrounding when locked.")
|
||||
}
|
||||
|
||||
func testTimerWhenUnlocked() {
|
||||
@Test
|
||||
mutating func timerWhenUnlocked() {
|
||||
setupTimer(unlocked: true, backgroundedAt: now)
|
||||
XCTAssertFalse(timer.computeLockState(didBecomeActiveAt: now + 1),
|
||||
"The app should remain unlocked when it was unlocked and backgrounded for less then the grace period.")
|
||||
#expect(!timer.computeLockState(didBecomeActiveAt: now + 1),
|
||||
"The app should remain unlocked when it was unlocked and backgrounded for less then the grace period.")
|
||||
|
||||
setupTimer(unlocked: true, backgroundedAt: now)
|
||||
XCTAssertFalse(timer.computeLockState(didBecomeActiveAt: now + halfGracePeriod),
|
||||
"The app should remain unlocked when it was unlocked and backgrounded for less then the grace period.")
|
||||
#expect(!timer.computeLockState(didBecomeActiveAt: now + halfGracePeriod),
|
||||
"The app should remain unlocked when it was unlocked and backgrounded for less then the grace period.")
|
||||
|
||||
setupTimer(unlocked: true, backgroundedAt: now)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now + gracePeriod),
|
||||
"The app should become locked when it was unlocked and backgrounded for more than the grace period.")
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now + gracePeriod),
|
||||
"The app should become locked when it was unlocked and backgrounded for more than the grace period.")
|
||||
|
||||
setupTimer(unlocked: true, backgroundedAt: now)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now + gracePeriodX10),
|
||||
"The app should become locked when it was unlocked and backgrounded for more than the grace period.")
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now + gracePeriodX10),
|
||||
"The app should become locked when it was unlocked and backgrounded for more than the grace period.")
|
||||
}
|
||||
|
||||
func testTimerRepeatingWithinGracePeriod() {
|
||||
@Test
|
||||
mutating func timerRepeatingWithinGracePeriod() {
|
||||
setupTimer(unlocked: true, backgroundedAt: now)
|
||||
|
||||
var nextCheck = now + halfGracePeriod
|
||||
XCTAssertFalse(timer.computeLockState(didBecomeActiveAt: nextCheck),
|
||||
"The app should remain unlocked when it was unlocked and backgrounded for less then the grace period.")
|
||||
#expect(!timer.computeLockState(didBecomeActiveAt: nextCheck),
|
||||
"The app should remain unlocked when it was unlocked and backgrounded for less then the grace period.")
|
||||
timer.applicationDidEnterBackground(date: nextCheck)
|
||||
|
||||
nextCheck = now + gracePeriod
|
||||
XCTAssertFalse(timer.computeLockState(didBecomeActiveAt: nextCheck),
|
||||
"The app should remain unlocked when repeating the backgrounded and foreground within the grace period.")
|
||||
#expect(!timer.computeLockState(didBecomeActiveAt: nextCheck),
|
||||
"The app should remain unlocked when repeating the backgrounded and foreground within the grace period.")
|
||||
timer.applicationDidEnterBackground(date: nextCheck)
|
||||
|
||||
nextCheck = now + gracePeriod + halfGracePeriod
|
||||
XCTAssertFalse(timer.computeLockState(didBecomeActiveAt: nextCheck),
|
||||
"The app should remain unlocked when repeating the backgrounded and foreground within the grace period.")
|
||||
#expect(!timer.computeLockState(didBecomeActiveAt: nextCheck),
|
||||
"The app should remain unlocked when repeating the backgrounded and foreground within the grace period.")
|
||||
timer.applicationDidEnterBackground(date: nextCheck)
|
||||
|
||||
nextCheck = now + gracePeriodX2
|
||||
XCTAssertFalse(timer.computeLockState(didBecomeActiveAt: nextCheck),
|
||||
"The app should remain unlocked when repeating the backgrounded and foreground within the grace period.")
|
||||
#expect(!timer.computeLockState(didBecomeActiveAt: nextCheck),
|
||||
"The app should remain unlocked when repeating the backgrounded and foreground within the grace period.")
|
||||
timer.applicationDidEnterBackground(date: nextCheck)
|
||||
|
||||
nextCheck = now + gracePeriodX10
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: nextCheck),
|
||||
"The app should become locked however when finally staying backgrounded for longer than the grace period.")
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: nextCheck),
|
||||
"The app should become locked however when finally staying backgrounded for longer than the grace period.")
|
||||
}
|
||||
|
||||
func testTimerWithLongForeground() {
|
||||
@Test
|
||||
mutating func timerWithLongForeground() {
|
||||
setupTimer(unlocked: true)
|
||||
|
||||
let backgroundDate = now + gracePeriodX10
|
||||
timer.applicationDidEnterBackground(date: backgroundDate)
|
||||
|
||||
XCTAssertFalse(timer.computeLockState(didBecomeActiveAt: backgroundDate + 1),
|
||||
"The grace period should be measured from the time the app was backgrounded, and not when it was unlocked.")
|
||||
#expect(!timer.computeLockState(didBecomeActiveAt: backgroundDate + 1),
|
||||
"The grace period should be measured from the time the app was backgrounded, and not when it was unlocked.")
|
||||
}
|
||||
|
||||
func testChangingTimeLocksApp() {
|
||||
@Test
|
||||
mutating func changingTimeLocksApp() {
|
||||
setupTimer(unlocked: true, backgroundedAt: now)
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now - 1),
|
||||
"The the device's clock is changed to before the app was backgrounded, the device should remain locked.")
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now - 1),
|
||||
"The the device's clock is changed to before the app was backgrounded, the device should remain locked.")
|
||||
}
|
||||
|
||||
func testNoGracePeriod() {
|
||||
@Test
|
||||
mutating func noGracePeriod() {
|
||||
// Given a timer with no grace period that is in the background.
|
||||
setupTimer(gracePeriod: 0, unlocked: true)
|
||||
let backgroundDate = now + 1
|
||||
timer.applicationDidEnterBackground(date: backgroundDate)
|
||||
|
||||
// Then the app should be locked immediately.
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: backgroundDate))
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: backgroundDate))
|
||||
}
|
||||
|
||||
func testResignActive() {
|
||||
@Test
|
||||
mutating func resignActive() {
|
||||
// Given a timer with no grace period.
|
||||
setupTimer(gracePeriod: 0, unlocked: true)
|
||||
|
||||
@@ -158,36 +163,32 @@ class AppLockTimerTests: XCTestCase {
|
||||
timer.applicationDidEnterBackground(date: now)
|
||||
|
||||
// Then the app should be locked.
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now + 1))
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now + 1))
|
||||
|
||||
// When the app resigns active but doesn't enter the background.
|
||||
// (Nothing to do here, we just don't call applicationDidEnterBackground).
|
||||
|
||||
// Then the app should also remain locked.
|
||||
XCTAssertTrue(timer.computeLockState(didBecomeActiveAt: now + 2))
|
||||
#expect(timer.computeLockState(didBecomeActiveAt: now + 2))
|
||||
|
||||
// When unlocking the app and resigning active (but not entering the background)
|
||||
timer.registerUnlock()
|
||||
// (Again, nothing to do here for resigning active)
|
||||
|
||||
// Then the app should not become locked.
|
||||
XCTAssertFalse(timer.computeLockState(didBecomeActiveAt: now + 3))
|
||||
#expect(!timer.computeLockState(didBecomeActiveAt: now + 3))
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
/// Sets up the timer for testing.
|
||||
/// - Parameters:
|
||||
/// - gracePeriod: Set up the test with a custom grace period for the timer. Defaults to 3 minutes.
|
||||
/// - unlocked: Whether the timer should consider itself unlocked or not.
|
||||
/// - backgroundedDate: If not nil, the timer will consider the app to have been backgrounded at the specified date.
|
||||
private func setupTimer(gracePeriod: TimeInterval = 180, unlocked: Bool, backgroundedAt backgroundedDate: Date? = nil) {
|
||||
timer = AppLockTimer(gracePeriod: gracePeriod)
|
||||
private mutating func setupTimer(gracePeriod: TimeInterval = 180, unlocked: Bool, backgroundedAt backgroundedDate: Date? = nil) {
|
||||
let timer = AppLockTimer(gracePeriod: gracePeriod)
|
||||
if unlocked {
|
||||
timer.registerUnlock()
|
||||
}
|
||||
if let backgroundedDate {
|
||||
timer.applicationDidEnterBackground(date: backgroundedDate)
|
||||
}
|
||||
self.timer = timer
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user