mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +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:
@@ -9,10 +9,11 @@
|
||||
import Combine
|
||||
@testable import ElementX
|
||||
import Foundation
|
||||
import XCTest
|
||||
import Testing
|
||||
|
||||
@MainActor
|
||||
class AudioPlayerStateTests: XCTestCase {
|
||||
@Suite
|
||||
struct AudioPlayerStateTests {
|
||||
static let audioDuration = 10.0
|
||||
private var audioPlayerState: AudioPlayerState!
|
||||
private var audioPlayerMock: AudioPlayerMock!
|
||||
@@ -36,39 +37,42 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
return audioPlayerMock
|
||||
}
|
||||
|
||||
override func setUp() async throws {
|
||||
init() async {
|
||||
audioPlayerActionsSubject = .init()
|
||||
audioPlayerSeekCallsSubject = .init()
|
||||
audioPlayerState = AudioPlayerState(id: .timelineItemIdentifier(.randomEvent), title: "", duration: Self.audioDuration)
|
||||
audioPlayerMock = buildAudioPlayerMock()
|
||||
audioPlayerMock.seekToClosure = { [weak self] progress in
|
||||
self?.audioPlayerMock.currentTime = Self.audioDuration * progress
|
||||
audioPlayerMock.seekToClosure = { [audioPlayerMock] progress in
|
||||
audioPlayerMock?.currentTime = Self.audioDuration * progress
|
||||
}
|
||||
}
|
||||
|
||||
func testAttach() {
|
||||
@Test
|
||||
func attach() {
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
XCTAssert(audioPlayerState.isAttached)
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .loading)
|
||||
#expect(audioPlayerState.isAttached)
|
||||
#expect(audioPlayerState.playbackState == .loading)
|
||||
}
|
||||
|
||||
func testDetach() {
|
||||
@Test
|
||||
mutating func detach() {
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
audioPlayerState.detachAudioPlayer()
|
||||
XCTAssert(audioPlayerMock.stopCalled)
|
||||
XCTAssertFalse(audioPlayerState.isAttached)
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
||||
XCTAssertFalse(audioPlayerState.showProgressIndicator)
|
||||
#expect(audioPlayerMock.stopCalled)
|
||||
#expect(!audioPlayerState.isAttached)
|
||||
#expect(audioPlayerState.playbackState == .stopped)
|
||||
#expect(!audioPlayerState.showProgressIndicator)
|
||||
}
|
||||
|
||||
func testDelayedState() async throws {
|
||||
@Test
|
||||
func delayedState() async throws {
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
XCTAssert(audioPlayerState.isAttached)
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .loading)
|
||||
XCTAssertEqual(audioPlayerState.playerButtonPlaybackState, .stopped)
|
||||
#expect(audioPlayerState.isAttached)
|
||||
#expect(audioPlayerState.playbackState == .loading)
|
||||
#expect(audioPlayerState.playerButtonPlaybackState == .stopped)
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerState.$playerButtonPlaybackState) { output in
|
||||
switch output {
|
||||
@@ -80,13 +84,14 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
}
|
||||
try await deferred.fulfill()
|
||||
|
||||
XCTAssertEqual(audioPlayerState.playerButtonPlaybackState, .loading)
|
||||
#expect(audioPlayerState.playerButtonPlaybackState == .loading)
|
||||
}
|
||||
|
||||
func testOtherActionsAreNotDelayed() async throws {
|
||||
@Test
|
||||
func otherActionsAreNotDelayed() async throws {
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .loading)
|
||||
XCTAssertEqual(audioPlayerState.playerButtonPlaybackState, .stopped)
|
||||
#expect(audioPlayerState.playbackState == .loading)
|
||||
#expect(audioPlayerState.playerButtonPlaybackState == .stopped)
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerState.$playerButtonPlaybackState) { output in
|
||||
switch output {
|
||||
@@ -99,53 +104,48 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
|
||||
audioPlayerActionsSubject.send(.didStartPlaying)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .playing)
|
||||
XCTAssertEqual(audioPlayerState.playerButtonPlaybackState, .playing)
|
||||
#expect(audioPlayerState.playbackState == .playing)
|
||||
#expect(audioPlayerState.playerButtonPlaybackState == .playing)
|
||||
}
|
||||
|
||||
func testReportError() {
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
||||
@Test
|
||||
mutating func reportError() {
|
||||
#expect(audioPlayerState.playbackState == .stopped)
|
||||
audioPlayerState.reportError()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .error)
|
||||
#expect(audioPlayerState.playbackState == .error)
|
||||
}
|
||||
|
||||
func testUpdateProgress() async {
|
||||
@Test
|
||||
mutating func updateProgress() async {
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
// If we try to set a negative progress, the new progress must be 0.0
|
||||
do {
|
||||
await audioPlayerState.updateState(progress: -5.0)
|
||||
XCTAssertEqual(audioPlayerState.progress, 0.0)
|
||||
XCTAssertEqual(audioPlayerMock.seekToReceivedProgress, 0.0)
|
||||
}
|
||||
|
||||
// If we try to set a progress > 1.0, the new progress must be 1.0
|
||||
do {
|
||||
await audioPlayerState.updateState(progress: 1.5)
|
||||
XCTAssertEqual(audioPlayerState.progress, 1.0)
|
||||
XCTAssertEqual(audioPlayerMock.seekToReceivedProgress, 1.0)
|
||||
}
|
||||
|
||||
do {
|
||||
audioPlayerMock.state = .stopped
|
||||
await audioPlayerState.updateState(progress: 0.4)
|
||||
XCTAssertEqual(audioPlayerState.progress, 0.4)
|
||||
XCTAssertEqual(audioPlayerMock.seekToReceivedProgress, 0.4)
|
||||
XCTAssertFalse(audioPlayerState.isPublishingProgress)
|
||||
}
|
||||
|
||||
do {
|
||||
audioPlayerMock.state = .playing
|
||||
await audioPlayerState.updateState(progress: 0.4)
|
||||
XCTAssertEqual(audioPlayerState.progress, 0.4)
|
||||
XCTAssertEqual(audioPlayerMock.seekToReceivedProgress, 0.4)
|
||||
XCTAssert(audioPlayerState.isPublishingProgress)
|
||||
}
|
||||
// If we try to set a negative progress, the new progress must be 0.0
|
||||
await audioPlayerState.updateState(progress: -5.0)
|
||||
#expect(audioPlayerState.progress == 0.0)
|
||||
#expect(audioPlayerMock.seekToReceivedProgress == 0.0)
|
||||
|
||||
// If we try to set a progress > 1.0, the new progress must be 1.0
|
||||
await audioPlayerState.updateState(progress: 1.5)
|
||||
#expect(audioPlayerState.progress == 1.0)
|
||||
#expect(audioPlayerMock.seekToReceivedProgress == 1.0)
|
||||
|
||||
audioPlayerMock.state = .stopped
|
||||
await audioPlayerState.updateState(progress: 0.4)
|
||||
#expect(audioPlayerState.progress == 0.4)
|
||||
#expect(audioPlayerMock.seekToReceivedProgress == 0.4)
|
||||
#expect(!audioPlayerState.isPublishingProgress)
|
||||
|
||||
audioPlayerMock.state = .playing
|
||||
await audioPlayerState.updateState(progress: 0.4)
|
||||
#expect(audioPlayerState.progress == 0.4)
|
||||
#expect(audioPlayerMock.seekToReceivedProgress == 0.4)
|
||||
#expect(audioPlayerState.isPublishingProgress)
|
||||
}
|
||||
|
||||
func testHandlingAudioPlayerActionDidStartLoading() async throws {
|
||||
|
||||
@Test
|
||||
func handlingAudioPlayerActionDidStartLoading() async throws {
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerState.$playbackState) { action in
|
||||
switch action {
|
||||
case .loading:
|
||||
@@ -157,15 +157,16 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
|
||||
audioPlayerActionsSubject.send(.didStartLoading)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .loading)
|
||||
#expect(audioPlayerState.playbackState == .loading)
|
||||
}
|
||||
|
||||
func testHandlingAudioPlayerActionDidFinishLoading() async throws {
|
||||
|
||||
@Test
|
||||
mutating func handlingAudioPlayerActionDidFinishLoading() async throws {
|
||||
audioPlayerMock.duration = 10.0
|
||||
|
||||
audioPlayerState = AudioPlayerState(id: .timelineItemIdentifier(.randomEvent), title: "", duration: 0)
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerState.$playbackState) { action in
|
||||
switch action {
|
||||
case .readyToPlay:
|
||||
@@ -179,15 +180,16 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
try await deferred.fulfill()
|
||||
|
||||
// The state is expected to be .readyToPlay
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .readyToPlay)
|
||||
#expect(audioPlayerState.playbackState == .readyToPlay)
|
||||
// The duration should have been updated with the player's duration
|
||||
XCTAssertEqual(audioPlayerState.duration, audioPlayerMock.duration)
|
||||
#expect(audioPlayerState.duration == audioPlayerMock.duration)
|
||||
}
|
||||
|
||||
func testHandlingAudioPlayerActionDidStartPlaying() async throws {
|
||||
@Test
|
||||
mutating func handlingAudioPlayerActionDidStartPlaying() async throws {
|
||||
await audioPlayerState.updateState(progress: 0.4)
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerState.$playbackState) { action in
|
||||
switch action {
|
||||
case .playing:
|
||||
@@ -199,16 +201,17 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
|
||||
audioPlayerActionsSubject.send(.didStartPlaying)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(audioPlayerMock.seekToReceivedProgress, 0.4)
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .playing)
|
||||
XCTAssert(audioPlayerState.isPublishingProgress)
|
||||
XCTAssert(audioPlayerState.showProgressIndicator)
|
||||
#expect(audioPlayerMock.seekToReceivedProgress == 0.4)
|
||||
#expect(audioPlayerState.playbackState == .playing)
|
||||
#expect(audioPlayerState.isPublishingProgress)
|
||||
#expect(audioPlayerState.showProgressIndicator)
|
||||
}
|
||||
|
||||
func testHandlingAudioPlayerActionDidPausePlaying() async throws {
|
||||
@Test
|
||||
mutating func handlingAudioPlayerActionDidPausePlaying() async throws {
|
||||
await audioPlayerState.updateState(progress: 0.4)
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerState.$playbackState) { action in
|
||||
switch action {
|
||||
case .stopped:
|
||||
@@ -220,16 +223,17 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
|
||||
audioPlayerActionsSubject.send(.didPausePlaying)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
||||
XCTAssertEqual(audioPlayerState.progress, 0.4)
|
||||
XCTAssertFalse(audioPlayerState.isPublishingProgress)
|
||||
XCTAssert(audioPlayerState.showProgressIndicator)
|
||||
#expect(audioPlayerState.playbackState == .stopped)
|
||||
#expect(audioPlayerState.progress == 0.4)
|
||||
#expect(!audioPlayerState.isPublishingProgress)
|
||||
#expect(audioPlayerState.showProgressIndicator)
|
||||
}
|
||||
|
||||
func testHandlingAudioPlayerActionsidStopPlaying() async throws {
|
||||
@Test
|
||||
mutating func handlingAudioPlayerActionsidStopPlaying() async throws {
|
||||
await audioPlayerState.updateState(progress: 0.4)
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerState.$playbackState) { action in
|
||||
switch action {
|
||||
case .stopped:
|
||||
@@ -241,16 +245,17 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
|
||||
audioPlayerActionsSubject.send(.didStopPlaying)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
||||
XCTAssertEqual(audioPlayerState.progress, 0.4)
|
||||
XCTAssertFalse(audioPlayerState.isPublishingProgress)
|
||||
XCTAssert(audioPlayerState.showProgressIndicator)
|
||||
#expect(audioPlayerState.playbackState == .stopped)
|
||||
#expect(audioPlayerState.progress == 0.4)
|
||||
#expect(!audioPlayerState.isPublishingProgress)
|
||||
#expect(audioPlayerState.showProgressIndicator)
|
||||
}
|
||||
|
||||
func testAudioPlayerActionsDidFinishPlaying() async throws {
|
||||
@Test
|
||||
mutating func audioPlayerActionsDidFinishPlaying() async throws {
|
||||
await audioPlayerState.updateState(progress: 0.4)
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerState.$playbackState) { action in
|
||||
switch action {
|
||||
case .stopped:
|
||||
@@ -262,16 +267,17 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
|
||||
audioPlayerActionsSubject.send(.didFinishPlaying)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
||||
#expect(audioPlayerState.playbackState == .stopped)
|
||||
// Progress should be reset to 0
|
||||
XCTAssertEqual(audioPlayerState.progress, 0.0)
|
||||
XCTAssertFalse(audioPlayerState.isPublishingProgress)
|
||||
XCTAssertFalse(audioPlayerState.showProgressIndicator)
|
||||
#expect(audioPlayerState.progress == 0.0)
|
||||
#expect(!audioPlayerState.isPublishingProgress)
|
||||
#expect(!audioPlayerState.showProgressIndicator)
|
||||
}
|
||||
|
||||
func testAudioPlayerActionsDidFailed() async throws {
|
||||
@Test
|
||||
func audioPlayerActionsDidFailed() async throws {
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
|
||||
let deferredPlayingState = deferFulfillment(audioPlayerState.$playbackState) { action in
|
||||
switch action {
|
||||
case .playing:
|
||||
@@ -282,8 +288,8 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
}
|
||||
audioPlayerActionsSubject.send(.didStartPlaying)
|
||||
try await deferredPlayingState.fulfill()
|
||||
XCTAssertFalse(audioPlayerState.showProgressIndicator)
|
||||
|
||||
#expect(!audioPlayerState.showProgressIndicator)
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerState.$playbackState) { action in
|
||||
switch action {
|
||||
case .error:
|
||||
@@ -295,8 +301,8 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
|
||||
audioPlayerActionsSubject.send(.didFailWithError(error: AudioPlayerError.genericError))
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .error)
|
||||
XCTAssertFalse(audioPlayerState.isPublishingProgress)
|
||||
XCTAssertFalse(audioPlayerState.showProgressIndicator)
|
||||
#expect(audioPlayerState.playbackState == .error)
|
||||
#expect(!audioPlayerState.isPublishingProgress)
|
||||
#expect(!audioPlayerState.showProgressIndicator)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user