From e001e75aba0332d66b41c92a002289d89f952fd1 Mon Sep 17 00:00:00 2001 From: Kiryl Kaveryn Date: Wed, 26 Feb 2025 20:17:55 +0400 Subject: [PATCH] [ios] add TrackRecordingManager unit tests Signed-off-by: Kiryl Kaveryn --- iphone/Maps/Maps.xcodeproj/project.pbxproj | 12 ++ .../TrackRecordingManagerTests.swift | 198 ++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 iphone/Maps/Tests/Core/TrackRecorder/TrackRecordingManagerTests.swift diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index d1066ddea5..0cf4419213 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -525,6 +525,7 @@ ED9857082C4ED02D00694F6C /* MailComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED9857072C4ED02D00694F6C /* MailComposer.swift */; }; ED9966802B94FBC20083CE55 /* ColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED99667D2B94FBC20083CE55 /* ColorPicker.swift */; }; ED9DDF882D6F151000645BC8 /* PlacePageTrackRecordingLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED9DDF872D6F151000645BC8 /* PlacePageTrackRecordingLayout.swift */; }; + ED9DDF9D2D6F6F7900645BC8 /* TrackRecordingManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED9DDF9B2D6F6DA300645BC8 /* TrackRecordingManagerTests.swift */; }; EDA1EAA42CC7ECAD00DBDCAA /* ElevationProfileFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA1EAA32CC7ECAD00DBDCAA /* ElevationProfileFormatter.swift */; }; EDBD68072B625724005DD151 /* LocationServicesDisabledAlert.xib in Resources */ = {isa = PBXBuildFile; fileRef = EDBD68062B625724005DD151 /* LocationServicesDisabledAlert.xib */; }; EDBD680B2B62572E005DD151 /* LocationServicesDisabledAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDBD680A2B62572E005DD151 /* LocationServicesDisabledAlert.swift */; }; @@ -1492,6 +1493,7 @@ ED9857072C4ED02D00694F6C /* MailComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailComposer.swift; sourceTree = ""; }; ED99667D2B94FBC20083CE55 /* ColorPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorPicker.swift; sourceTree = ""; }; ED9DDF872D6F151000645BC8 /* PlacePageTrackRecordingLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlacePageTrackRecordingLayout.swift; sourceTree = ""; }; + ED9DDF9B2D6F6DA300645BC8 /* TrackRecordingManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackRecordingManagerTests.swift; sourceTree = ""; }; EDA1EAA32CC7ECAD00DBDCAA /* ElevationProfileFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElevationProfileFormatter.swift; sourceTree = ""; }; EDBD68062B625724005DD151 /* LocationServicesDisabledAlert.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LocationServicesDisabledAlert.xib; sourceTree = ""; }; EDBD680A2B62572E005DD151 /* LocationServicesDisabledAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationServicesDisabledAlert.swift; sourceTree = ""; }; @@ -2767,6 +2769,7 @@ 4B4153B62BF9709100EE4B02 /* Core */ = { isa = PBXGroup; children = ( + ED9DDF982D6F6D8000645BC8 /* TrackRecorder */, EDF838AB2C00B9C7007E4E67 /* iCloudTests */, 4B4153B72BF970A000EE4B02 /* TextToSpeech */, ); @@ -3315,6 +3318,14 @@ path = ColorPicker; sourceTree = ""; }; + ED9DDF982D6F6D8000645BC8 /* TrackRecorder */ = { + isa = PBXGroup; + children = ( + ED9DDF9B2D6F6DA300645BC8 /* TrackRecordingManagerTests.swift */, + ); + path = TrackRecorder; + sourceTree = ""; + }; EDC4E3422C5D1BD3009286A2 /* RecentlyDeletedTests */ = { isa = PBXGroup; children = ( @@ -4911,6 +4922,7 @@ EDF838C32C00B9D6007E4E67 /* UbiquitousDirectoryMonitorDelegateMock.swift in Sources */, EDF838BE2C00B9D0007E4E67 /* LocalDirectoryMonitorDelegateMock.swift in Sources */, EDC4E3692C5E6F5B009286A2 /* MockRecentlyDeletedCategoriesManager.swift in Sources */, + ED9DDF9D2D6F6F7900645BC8 /* TrackRecordingManagerTests.swift in Sources */, EDF838BF2C00B9D0007E4E67 /* SynchronizationStateManagerTests.swift in Sources */, ED810EC52D566E9B00ECDE2C /* SearchOnMapTests.swift in Sources */, 4B83AE4B2C2E642100B0C3BC /* TTSTesterTest.m in Sources */, diff --git a/iphone/Maps/Tests/Core/TrackRecorder/TrackRecordingManagerTests.swift b/iphone/Maps/Tests/Core/TrackRecorder/TrackRecordingManagerTests.swift new file mode 100644 index 0000000000..ecb44380d2 --- /dev/null +++ b/iphone/Maps/Tests/Core/TrackRecorder/TrackRecordingManagerTests.swift @@ -0,0 +1,198 @@ +import XCTest +@testable import Organic_Maps__Debug_ + +final class TrackRecordingManagerTests: XCTestCase { + + private var trackRecordingManager: TrackRecordingManager! + + private var mockTrackRecorder: MockTrackRecorder.Type! + private var mockLocationService: MockLocationService.Type! + private var mockActivityManager: MockTrackRecordingActivityManager! + + override func setUp() { + super.setUp() + mockTrackRecorder = MockTrackRecorder.self + mockLocationService = MockLocationService.self + mockActivityManager = MockTrackRecordingActivityManager() + + trackRecordingManager = TrackRecordingManager( + trackRecorder: mockTrackRecorder, + locationService: mockLocationService, + activityManager: mockActivityManager + ) + } + + override func tearDown() { + trackRecordingManager = nil + mockTrackRecorder.reset() + mockLocationService.reset() + mockActivityManager = nil + super.tearDown() + } + + func test_GivenInitialSetup_WhenLocationEnabled_ThenStateIsInactive() { + mockLocationService.locationIsProhibited = false + mockTrackRecorder.trackRecordingIsEnabled = false + + trackRecordingManager.setup() + XCTAssertTrue(trackRecordingManager.recordingState == .inactive) + } + + func test_GivenInitialSetup_WhenLocationDisabled_ThenShouldHandleErrorAndIncativeState() { + mockLocationService.locationIsProhibited = true + + trackRecordingManager.setup() + + XCTAssertTrue(mockLocationService.checkLocationStatusCalled) + XCTAssertTrue(trackRecordingManager.recordingState == .inactive) + } + + func test_GivenStartRecording_WhenLocationEnabled_ThenSuccess() { + mockLocationService.locationIsProhibited = false + mockTrackRecorder.trackRecordingIsEnabled = false + + trackRecordingManager.processAction(.start) + + XCTAssertTrue(mockTrackRecorder.startTrackRecordingCalled) + XCTAssertTrue(mockActivityManager.startCalled) + XCTAssertTrue(trackRecordingManager.recordingState == .active) + } + + func test_GivenStartRecording_WhenLocationDisabled_ThenShouldFail() { + mockLocationService.locationIsProhibited = true + + trackRecordingManager.processAction(.start) { result in + switch result { + case .success: + XCTFail("Should not succeed") + case .error(let error): + switch error { + case .locationIsProhibited: + XCTAssertTrue(true) + default: + XCTFail("Unexpected error: \(error)") + } + } + } + XCTAssertFalse(self.mockTrackRecorder.startTrackRecordingCalled) + XCTAssertTrue(trackRecordingManager.recordingState == .inactive) + } + + func test_GivenStopRecording_WhenLocationEnabled_ThenSuccess() { + mockTrackRecorder.trackRecordingIsEnabled = true + mockTrackRecorder.trackRecordingIsEmpty = false + + trackRecordingManager.processAction(.stopAndSave(name: "Test Track")) { result in + switch result { + case .success: + XCTAssertTrue(true) + case .error(let error): + XCTFail("Unexpected error: \(error)") + } + } + XCTAssertTrue(mockTrackRecorder.stopTrackRecordingCalled) + XCTAssertTrue(mockTrackRecorder.saveTrackRecordingCalled) + XCTAssertTrue(mockActivityManager.stopCalled) + XCTAssertTrue(trackRecordingManager.recordingState == .inactive) + } + + func test_GivenStopRecording_WhenTrackIsEmpty_ThenShouldFail() { + mockTrackRecorder.trackRecordingIsEnabled = true + mockTrackRecorder.trackRecordingIsEmpty = true + + trackRecordingManager.processAction(.stopAndSave(name: "Test Track")) { result in + switch result { + case .success: + XCTFail("Should not succeed") + case .error(let error): + switch error { + case .trackIsEmpty: + XCTAssertTrue(true) + default: + XCTFail("Unexpected error: \(error)") + } + } + } + XCTAssertFalse(mockTrackRecorder.saveTrackRecordingCalled) + XCTAssertTrue(trackRecordingManager.recordingState == .inactive) + } +} + +// MARK: - Mock Classes + +private final class MockTrackRecorder: TrackRecorder { + static var trackRecordingIsEnabled = false + static var trackRecordingIsEmpty = false + static var startTrackRecordingCalled = false + static var stopTrackRecordingCalled = false + static var saveTrackRecordingCalled = false + + static func reset() { + trackRecordingIsEnabled = false + trackRecordingIsEmpty = false + startTrackRecordingCalled = false + stopTrackRecordingCalled = false + saveTrackRecordingCalled = false + } + + static func isTrackRecordingEnabled() -> Bool { + return trackRecordingIsEnabled + } + + static func isTrackRecordingEmpty() -> Bool { + return trackRecordingIsEmpty + } + + static func startTrackRecording() { + startTrackRecordingCalled = true + trackRecordingIsEnabled = true + } + + static func stopTrackRecording() { + stopTrackRecordingCalled = true + trackRecordingIsEnabled = false + } + + static func saveTrackRecording(withName name: String) { + saveTrackRecordingCalled = true + } + + static func setTrackRecordingUpdateHandler(_ handler: ((TrackInfo) -> Void)?) {} + + static func trackRecordingElevationInfo() -> ElevationProfileData { + ElevationProfileData() + } +} + +private final class MockLocationService: LocationService { + static var locationIsProhibited = false + static var checkLocationStatusCalled = false + + static func reset() { + locationIsProhibited = false + checkLocationStatusCalled = false + } + + static func isLocationProhibited() -> Bool { + return locationIsProhibited + } + + static func checkLocationStatus() { + checkLocationStatusCalled = true + } +} + +final class MockTrackRecordingActivityManager: TrackRecordingActivityManager { + var startCalled = false + var stopCalled = false + + func start(with info: TrackInfo) throws { + startCalled = true + } + + func stop() { + stopCalled = true + } + + func update(_ info: TrackInfo) {} +}