mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Add unit tests for voice messages (#1869)
This commit is contained in:
@@ -650,6 +650,7 @@
|
||||
C0DC02E2B91DC76A4D1A0E7F /* OnboardingScreenBackgroundImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F3450F4C32D73532DBBC1A2 /* OnboardingScreenBackgroundImage.swift */; };
|
||||
C11939FDC40716C4387275A4 /* NotificationSettingsEditScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8544F7058D31DBEB8DBFF0F5 /* NotificationSettingsEditScreenViewModelTests.swift */; };
|
||||
C13128AAA787A4C2CBE4EE82 /* MessageForwardingScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC10CCC8D68B863E20660DBC /* MessageForwardingScreenViewModelProtocol.swift */; };
|
||||
C1429699A6A5BB09A25775C1 /* AudioPlayerStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89233612A8632AD7E2803620 /* AudioPlayerStateTests.swift */; };
|
||||
C19085A284D54A166A64A86C /* AudioPlayerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA88C615D8BFCCEF0D2FEAC9 /* AudioPlayerState.swift */; };
|
||||
C1910A16BDF131FECA77BE22 /* EmojiPickerScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEA38B9851CFCC4D67F5587D /* EmojiPickerScreenCoordinator.swift */; };
|
||||
C1A5C386319835FB0C77736B /* ReportContentScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A16CD2C62CB7DB78A4238485 /* ReportContentScreenCoordinator.swift */; };
|
||||
@@ -1315,6 +1316,7 @@
|
||||
8872E9C5E91E9F2BFC4EBCCA /* AlignedScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlignedScrollView.swift; sourceTree = "<group>"; };
|
||||
8896CDD20CA2D87EA3B848A1 /* RoomNotificationSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreen.swift; sourceTree = "<group>"; };
|
||||
889DEDD63C68ABDA8AD29812 /* VoiceMessageMediaManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageMediaManagerProtocol.swift; sourceTree = "<group>"; };
|
||||
89233612A8632AD7E2803620 /* AudioPlayerStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerStateTests.swift; sourceTree = "<group>"; };
|
||||
892E29C98C4E8182C9037F84 /* TimelineStyler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyler.swift; sourceTree = "<group>"; };
|
||||
893777A4997BBDB68079D4F5 /* ArrayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrayTests.swift; sourceTree = "<group>"; };
|
||||
8977176AB534AA41630395BC /* LegalInformationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
@@ -2760,6 +2762,7 @@
|
||||
893777A4997BBDB68079D4F5 /* ArrayTests.swift */,
|
||||
AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */,
|
||||
37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */,
|
||||
89233612A8632AD7E2803620 /* AudioPlayerStateTests.swift */,
|
||||
6DFCAA239095A116976E32C4 /* BackgroundTaskTests.swift */,
|
||||
EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */,
|
||||
7AB7ED3A898B07976F3AA90F /* BugReportViewModelTests.swift */,
|
||||
@@ -4550,6 +4553,7 @@
|
||||
3EC698F80DDEEFA273857841 /* ArrayTests.swift in Sources */,
|
||||
90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */,
|
||||
5100F53E6884A15F9BA07CC3 /* AttributedStringTests.swift in Sources */,
|
||||
C1429699A6A5BB09A25775C1 /* AudioPlayerStateTests.swift in Sources */,
|
||||
0F9E38A75337D0146652ACAB /* BackgroundTaskTests.swift in Sources */,
|
||||
7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */,
|
||||
C7CFDB4929DDD9A3B5BA085D /* BugReportViewModelTests.swift in Sources */,
|
||||
|
||||
@@ -115,6 +115,94 @@ class AnalyticsClientMock: AnalyticsClientProtocol {
|
||||
updateUserPropertiesClosure?(userProperties)
|
||||
}
|
||||
}
|
||||
class AudioPlayerMock: AudioPlayerProtocol {
|
||||
var actions: AnyPublisher<AudioPlayerAction, Never> {
|
||||
get { return underlyingActions }
|
||||
set(value) { underlyingActions = value }
|
||||
}
|
||||
var underlyingActions: AnyPublisher<AudioPlayerAction, Never>!
|
||||
var mediaSource: MediaSourceProxy?
|
||||
var currentTime: TimeInterval {
|
||||
get { return underlyingCurrentTime }
|
||||
set(value) { underlyingCurrentTime = value }
|
||||
}
|
||||
var underlyingCurrentTime: TimeInterval!
|
||||
var url: URL?
|
||||
var state: MediaPlayerState {
|
||||
get { return underlyingState }
|
||||
set(value) { underlyingState = value }
|
||||
}
|
||||
var underlyingState: MediaPlayerState!
|
||||
|
||||
//MARK: - load
|
||||
|
||||
var loadMediaSourceUsingCallsCount = 0
|
||||
var loadMediaSourceUsingCalled: Bool {
|
||||
return loadMediaSourceUsingCallsCount > 0
|
||||
}
|
||||
var loadMediaSourceUsingReceivedArguments: (mediaSource: MediaSourceProxy, url: URL)?
|
||||
var loadMediaSourceUsingReceivedInvocations: [(mediaSource: MediaSourceProxy, url: URL)] = []
|
||||
var loadMediaSourceUsingClosure: ((MediaSourceProxy, URL) -> Void)?
|
||||
|
||||
func load(mediaSource: MediaSourceProxy, using url: URL) {
|
||||
loadMediaSourceUsingCallsCount += 1
|
||||
loadMediaSourceUsingReceivedArguments = (mediaSource: mediaSource, url: url)
|
||||
loadMediaSourceUsingReceivedInvocations.append((mediaSource: mediaSource, url: url))
|
||||
loadMediaSourceUsingClosure?(mediaSource, url)
|
||||
}
|
||||
//MARK: - play
|
||||
|
||||
var playCallsCount = 0
|
||||
var playCalled: Bool {
|
||||
return playCallsCount > 0
|
||||
}
|
||||
var playClosure: (() -> Void)?
|
||||
|
||||
func play() {
|
||||
playCallsCount += 1
|
||||
playClosure?()
|
||||
}
|
||||
//MARK: - pause
|
||||
|
||||
var pauseCallsCount = 0
|
||||
var pauseCalled: Bool {
|
||||
return pauseCallsCount > 0
|
||||
}
|
||||
var pauseClosure: (() -> Void)?
|
||||
|
||||
func pause() {
|
||||
pauseCallsCount += 1
|
||||
pauseClosure?()
|
||||
}
|
||||
//MARK: - stop
|
||||
|
||||
var stopCallsCount = 0
|
||||
var stopCalled: Bool {
|
||||
return stopCallsCount > 0
|
||||
}
|
||||
var stopClosure: (() -> Void)?
|
||||
|
||||
func stop() {
|
||||
stopCallsCount += 1
|
||||
stopClosure?()
|
||||
}
|
||||
//MARK: - seek
|
||||
|
||||
var seekToCallsCount = 0
|
||||
var seekToCalled: Bool {
|
||||
return seekToCallsCount > 0
|
||||
}
|
||||
var seekToReceivedProgress: Double?
|
||||
var seekToReceivedInvocations: [Double] = []
|
||||
var seekToClosure: ((Double) async -> Void)?
|
||||
|
||||
func seek(to progress: Double) async {
|
||||
seekToCallsCount += 1
|
||||
seekToReceivedProgress = progress
|
||||
seekToReceivedInvocations.append(progress)
|
||||
await seekToClosure?(progress)
|
||||
}
|
||||
}
|
||||
class BugReportServiceMock: BugReportServiceProtocol {
|
||||
var isRunning: Bool {
|
||||
get { return underlyingIsRunning }
|
||||
@@ -226,6 +314,89 @@ class CompletionSuggestionServiceMock: CompletionSuggestionServiceProtocol {
|
||||
setSuggestionTriggerClosure?(suggestionTrigger)
|
||||
}
|
||||
}
|
||||
class MediaPlayerMock: MediaPlayerProtocol {
|
||||
var mediaSource: MediaSourceProxy?
|
||||
var currentTime: TimeInterval {
|
||||
get { return underlyingCurrentTime }
|
||||
set(value) { underlyingCurrentTime = value }
|
||||
}
|
||||
var underlyingCurrentTime: TimeInterval!
|
||||
var url: URL?
|
||||
var state: MediaPlayerState {
|
||||
get { return underlyingState }
|
||||
set(value) { underlyingState = value }
|
||||
}
|
||||
var underlyingState: MediaPlayerState!
|
||||
|
||||
//MARK: - load
|
||||
|
||||
var loadMediaSourceUsingCallsCount = 0
|
||||
var loadMediaSourceUsingCalled: Bool {
|
||||
return loadMediaSourceUsingCallsCount > 0
|
||||
}
|
||||
var loadMediaSourceUsingReceivedArguments: (mediaSource: MediaSourceProxy, url: URL)?
|
||||
var loadMediaSourceUsingReceivedInvocations: [(mediaSource: MediaSourceProxy, url: URL)] = []
|
||||
var loadMediaSourceUsingClosure: ((MediaSourceProxy, URL) -> Void)?
|
||||
|
||||
func load(mediaSource: MediaSourceProxy, using url: URL) {
|
||||
loadMediaSourceUsingCallsCount += 1
|
||||
loadMediaSourceUsingReceivedArguments = (mediaSource: mediaSource, url: url)
|
||||
loadMediaSourceUsingReceivedInvocations.append((mediaSource: mediaSource, url: url))
|
||||
loadMediaSourceUsingClosure?(mediaSource, url)
|
||||
}
|
||||
//MARK: - play
|
||||
|
||||
var playCallsCount = 0
|
||||
var playCalled: Bool {
|
||||
return playCallsCount > 0
|
||||
}
|
||||
var playClosure: (() -> Void)?
|
||||
|
||||
func play() {
|
||||
playCallsCount += 1
|
||||
playClosure?()
|
||||
}
|
||||
//MARK: - pause
|
||||
|
||||
var pauseCallsCount = 0
|
||||
var pauseCalled: Bool {
|
||||
return pauseCallsCount > 0
|
||||
}
|
||||
var pauseClosure: (() -> Void)?
|
||||
|
||||
func pause() {
|
||||
pauseCallsCount += 1
|
||||
pauseClosure?()
|
||||
}
|
||||
//MARK: - stop
|
||||
|
||||
var stopCallsCount = 0
|
||||
var stopCalled: Bool {
|
||||
return stopCallsCount > 0
|
||||
}
|
||||
var stopClosure: (() -> Void)?
|
||||
|
||||
func stop() {
|
||||
stopCallsCount += 1
|
||||
stopClosure?()
|
||||
}
|
||||
//MARK: - seek
|
||||
|
||||
var seekToCallsCount = 0
|
||||
var seekToCalled: Bool {
|
||||
return seekToCallsCount > 0
|
||||
}
|
||||
var seekToReceivedProgress: Double?
|
||||
var seekToReceivedInvocations: [Double] = []
|
||||
var seekToClosure: ((Double) async -> Void)?
|
||||
|
||||
func seek(to progress: Double) async {
|
||||
seekToCallsCount += 1
|
||||
seekToReceivedProgress = progress
|
||||
seekToReceivedInvocations.append(progress)
|
||||
await seekToClosure?(progress)
|
||||
}
|
||||
}
|
||||
class NotificationCenterMock: NotificationCenterProtocol {
|
||||
|
||||
//MARK: - post
|
||||
@@ -1914,4 +2085,32 @@ class UserNotificationCenterMock: UserNotificationCenterProtocol {
|
||||
}
|
||||
}
|
||||
}
|
||||
class VoiceMessageMediaManagerMock: VoiceMessageMediaManagerProtocol {
|
||||
|
||||
//MARK: - loadVoiceMessageFromSource
|
||||
|
||||
var loadVoiceMessageFromSourceBodyThrowableError: Error?
|
||||
var loadVoiceMessageFromSourceBodyCallsCount = 0
|
||||
var loadVoiceMessageFromSourceBodyCalled: Bool {
|
||||
return loadVoiceMessageFromSourceBodyCallsCount > 0
|
||||
}
|
||||
var loadVoiceMessageFromSourceBodyReceivedArguments: (source: MediaSourceProxy, body: String?)?
|
||||
var loadVoiceMessageFromSourceBodyReceivedInvocations: [(source: MediaSourceProxy, body: String?)] = []
|
||||
var loadVoiceMessageFromSourceBodyReturnValue: URL!
|
||||
var loadVoiceMessageFromSourceBodyClosure: ((MediaSourceProxy, String?) async throws -> URL)?
|
||||
|
||||
func loadVoiceMessageFromSource(_ source: MediaSourceProxy, body: String?) async throws -> URL {
|
||||
if let error = loadVoiceMessageFromSourceBodyThrowableError {
|
||||
throw error
|
||||
}
|
||||
loadVoiceMessageFromSourceBodyCallsCount += 1
|
||||
loadVoiceMessageFromSourceBodyReceivedArguments = (source: source, body: body)
|
||||
loadVoiceMessageFromSourceBodyReceivedInvocations.append((source: source, body: body))
|
||||
if let loadVoiceMessageFromSourceBodyClosure = loadVoiceMessageFromSourceBodyClosure {
|
||||
return try await loadVoiceMessageFromSourceBodyClosure(source, body)
|
||||
} else {
|
||||
return loadVoiceMessageFromSourceBodyReturnValue
|
||||
}
|
||||
}
|
||||
}
|
||||
// swiftlint:enable all
|
||||
|
||||
@@ -30,3 +30,6 @@ enum AudioPlayerAction {
|
||||
protocol AudioPlayerProtocol: MediaPlayerProtocol {
|
||||
var actions: AnyPublisher<AudioPlayerAction, Never> { get }
|
||||
}
|
||||
|
||||
// sourcery: AutoMockable
|
||||
extension AudioPlayerProtocol { }
|
||||
|
||||
@@ -40,6 +40,10 @@ class AudioPlayerState: ObservableObject {
|
||||
var isAttached: Bool {
|
||||
audioPlayer != nil
|
||||
}
|
||||
|
||||
var isPublishingProgress: Bool {
|
||||
cancellableTimer != nil
|
||||
}
|
||||
|
||||
init(duration: Double, waveform: Waveform? = nil, progress: Double = 0.0) {
|
||||
self.duration = duration
|
||||
@@ -133,6 +137,7 @@ class AudioPlayerState: ObservableObject {
|
||||
|
||||
private func stopPublishProgress() {
|
||||
cancellableTimer?.cancel()
|
||||
cancellableTimer = nil
|
||||
}
|
||||
|
||||
private func restoreAudioPlayerState(audioPlayer: AudioPlayerProtocol) async {
|
||||
|
||||
@@ -37,3 +37,6 @@ protocol MediaPlayerProtocol {
|
||||
func stop()
|
||||
func seek(to progress: Double) async
|
||||
}
|
||||
|
||||
// sourcery: AutoMockable
|
||||
extension MediaPlayerProtocol { }
|
||||
|
||||
@@ -19,3 +19,6 @@ import Foundation
|
||||
protocol VoiceMessageMediaManagerProtocol {
|
||||
func loadVoiceMessageFromSource(_ source: MediaSourceProxy, body: String?) async throws -> URL
|
||||
}
|
||||
|
||||
// sourcery: AutoMockable
|
||||
extension VoiceMessageMediaManagerProtocol { }
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
//
|
||||
// Copyright 2023 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Combine
|
||||
@testable import ElementX
|
||||
import Foundation
|
||||
import XCTest
|
||||
|
||||
@MainActor
|
||||
class AudioPlayerStateTests: XCTestCase {
|
||||
private var audioPlayerState: AudioPlayerState!
|
||||
private var audioPlayerMock: AudioPlayerMock!
|
||||
|
||||
private var audioPlayerActionsSubject: PassthroughSubject<AudioPlayerAction, Never>!
|
||||
private var audioPlayerActions: AnyPublisher<AudioPlayerAction, Never> {
|
||||
audioPlayerActionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
private var audioPlayerSeekCallsSubject: PassthroughSubject<Double, Never>!
|
||||
private var audioPlayerSeekCalls: AnyPublisher<Double, Never> {
|
||||
audioPlayerSeekCallsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
private func buildAudioPlayerMock() -> AudioPlayerMock {
|
||||
let audioPlayerMock = AudioPlayerMock()
|
||||
audioPlayerMock.underlyingActions = audioPlayerActions
|
||||
audioPlayerMock.currentTime = 0.0
|
||||
audioPlayerMock.seekToClosure = { [audioPlayerSeekCallsSubject] progress in
|
||||
audioPlayerSeekCallsSubject?.send(progress)
|
||||
}
|
||||
return audioPlayerMock
|
||||
}
|
||||
|
||||
override func setUp() async throws {
|
||||
audioPlayerActionsSubject = .init()
|
||||
audioPlayerSeekCallsSubject = .init()
|
||||
audioPlayerState = AudioPlayerState(duration: 10.0)
|
||||
audioPlayerMock = buildAudioPlayerMock()
|
||||
}
|
||||
|
||||
func testAttach() async throws {
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
XCTAssert(audioPlayerState.isAttached)
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .loading)
|
||||
}
|
||||
|
||||
func testDetach() async throws {
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
audioPlayerState.detachAudioPlayer()
|
||||
XCTAssert(audioPlayerMock.stopCalled)
|
||||
XCTAssertFalse(audioPlayerState.isAttached)
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
||||
}
|
||||
|
||||
func testReportError() async throws {
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
||||
audioPlayerState.reportError(AudioPlayerError.genericError)
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .error)
|
||||
}
|
||||
|
||||
func testUpdateProgress() async throws {
|
||||
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 {
|
||||
await audioPlayerState.updateState(progress: 0.4)
|
||||
XCTAssertEqual(audioPlayerState.progress, 0.4)
|
||||
XCTAssertEqual(audioPlayerMock.seekToReceivedProgress, 0.4)
|
||||
}
|
||||
}
|
||||
|
||||
func testHandlingAudioPlayerActionDidStartLoading() async throws {
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerActions) { action in
|
||||
switch action {
|
||||
case .didStartLoading:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
audioPlayerActionsSubject.send(.didStartLoading)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .loading)
|
||||
}
|
||||
|
||||
func testHandlingAudioPlayerActionDidFinishLoading() async throws {
|
||||
let originalStateProgress = 0.4
|
||||
await audioPlayerState.updateState(progress: originalStateProgress)
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerActions) { action in
|
||||
switch action {
|
||||
case .didFinishLoading:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
// The progress should be restored
|
||||
let deferedProgress = deferFulfillment(audioPlayerSeekCalls) { progress in
|
||||
progress == originalStateProgress
|
||||
}
|
||||
|
||||
audioPlayerActionsSubject.send(.didFinishLoading)
|
||||
try await deferred.fulfill()
|
||||
try await deferedProgress.fulfill()
|
||||
|
||||
// The state is expected to be .readyToPlay
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .readyToPlay)
|
||||
}
|
||||
|
||||
func testHandlingAudioPlayerActionDidStartPlaying() async throws {
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerActions) { action in
|
||||
switch action {
|
||||
case .didStartPlaying:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
audioPlayerActionsSubject.send(.didStartPlaying)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .playing)
|
||||
XCTAssert(audioPlayerState.isPublishingProgress)
|
||||
}
|
||||
|
||||
func testHandlingAudioPlayerActionDidPausePlaying() async throws {
|
||||
await audioPlayerState.updateState(progress: 0.4)
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerActions) { action in
|
||||
switch action {
|
||||
case .didPausePlaying:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
audioPlayerActionsSubject.send(.didPausePlaying)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
||||
XCTAssertEqual(audioPlayerState.progress, 0.4)
|
||||
XCTAssertFalse(audioPlayerState.isPublishingProgress)
|
||||
}
|
||||
|
||||
func testHandlingAudioPlayerActionsidStopPlaying() async throws {
|
||||
await audioPlayerState.updateState(progress: 0.4)
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerActions) { action in
|
||||
switch action {
|
||||
case .didStopPlaying:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
audioPlayerActionsSubject.send(.didStopPlaying)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
||||
XCTAssertEqual(audioPlayerState.progress, 0.4)
|
||||
XCTAssertFalse(audioPlayerState.isPublishingProgress)
|
||||
}
|
||||
|
||||
func testAudioPlayerActionsDidFinishPlaying() async throws {
|
||||
await audioPlayerState.updateState(progress: 0.4)
|
||||
audioPlayerState.attachAudioPlayer(audioPlayerMock)
|
||||
|
||||
let deferred = deferFulfillment(audioPlayerActions) { action in
|
||||
switch action {
|
||||
case .didFinishPlaying:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
audioPlayerActionsSubject.send(.didFinishPlaying)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
||||
// Progress should be reset to 0
|
||||
XCTAssertEqual(audioPlayerState.progress, 0.0)
|
||||
XCTAssertFalse(audioPlayerState.isPublishingProgress)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user