diff --git a/AppDates/AppDates.xcodeproj/project.pbxproj b/AppDates/AppDates.xcodeproj/project.pbxproj index 0438af748..88e73cb76 100644 --- a/AppDates/AppDates.xcodeproj/project.pbxproj +++ b/AppDates/AppDates.xcodeproj/project.pbxproj @@ -9,7 +9,7 @@ /* Begin PBXBuildFile section */ 9941863792906D15DF2A3ECA /* Pods_App_AppDates.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E2984D28B27605D024FE0AC /* Pods_App_AppDates.framework */; }; A1A9C1B7F354E7604855D612 /* Pods_App_AppDates_AppDatesTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CE12953BBB7F7C65675973B /* Pods_App_AppDates_AppDatesTests.framework */; }; - CE75F3AE2D9A89AA0024BB43 /* AppDatesMock.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE75F3AD2D9A89AA0024BB43 /* AppDatesMock.generated.swift */; }; + A5B468202F2A1101002A4ECA /* AppDatesMocks.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B4681E2F2A1101002A4ECA /* AppDatesMocks.generated.swift */; }; CE815A672D60D75200CB9114 /* AppDates.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE815A5E2D60D75200CB9114 /* AppDates.framework */; }; CE815A792D60D78B00CB9114 /* Core.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE815A782D60D78B00CB9114 /* Core.framework */; }; CE815A7E2D60D7CC00CB9114 /* OEXFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CE815A7D2D60D7CC00CB9114 /* OEXFoundation */; }; @@ -73,11 +73,11 @@ 9E2984D28B27605D024FE0AC /* Pods_App_AppDates.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App_AppDates.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A3F5B654743233E0EBF20ACE /* Pods-App-AppDates.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-AppDates.debug.xcconfig"; path = "Target Support Files/Pods-App-AppDates/Pods-App-AppDates.debug.xcconfig"; sourceTree = ""; }; A4FF28047F07A8E553DD3C3F /* Pods-App-AppDates.releaseprod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-AppDates.releaseprod.xcconfig"; path = "Target Support Files/Pods-App-AppDates/Pods-App-AppDates.releaseprod.xcconfig"; sourceTree = ""; }; + A5B4681E2F2A1101002A4ECA /* AppDatesMocks.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDatesMocks.generated.swift; sourceTree = ""; }; AFC846633FC6ED95F9884DE0 /* Pods-App-AppDates-AppDatesTests.releasedev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-AppDates-AppDatesTests.releasedev.xcconfig"; path = "Target Support Files/Pods-App-AppDates-AppDatesTests/Pods-App-AppDates-AppDatesTests.releasedev.xcconfig"; sourceTree = ""; }; B3A97A12BDD649309E86E47F /* Pods-App-AppDates.releasestage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-AppDates.releasestage.xcconfig"; path = "Target Support Files/Pods-App-AppDates/Pods-App-AppDates.releasestage.xcconfig"; sourceTree = ""; }; B425DC0B44831EA155630C1D /* Pods-App-AppDates.debugstage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-AppDates.debugstage.xcconfig"; path = "Target Support Files/Pods-App-AppDates/Pods-App-AppDates.debugstage.xcconfig"; sourceTree = ""; }; CC47B8A74F999FBDA6DC2597 /* Pods-App-AppDates-AppDatesTests.debugprod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-AppDates-AppDatesTests.debugprod.xcconfig"; path = "Target Support Files/Pods-App-AppDates-AppDatesTests/Pods-App-AppDates-AppDatesTests.debugprod.xcconfig"; sourceTree = ""; }; - CE75F3AD2D9A89AA0024BB43 /* AppDatesMock.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDatesMock.generated.swift; sourceTree = ""; }; CE815A5E2D60D75200CB9114 /* AppDates.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AppDates.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CE815A662D60D75200CB9114 /* AppDatesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AppDatesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; CE815A782D60D78B00CB9114 /* Core.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Core.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -152,6 +152,14 @@ path = ../Pods; sourceTree = ""; }; + A5B4681F2F2A1101002A4ECA /* Generated */ = { + isa = PBXGroup; + children = ( + A5B4681E2F2A1101002A4ECA /* AppDatesMocks.generated.swift */, + ); + path = Generated; + sourceTree = ""; + }; CE815A542D60D75200CB9114 = { isa = PBXGroup; children = ( @@ -186,8 +194,8 @@ CE815AA22D60DD6B00CB9114 /* AppDatesTests */ = { isa = PBXGroup; children = ( + A5B4681F2F2A1101002A4ECA /* Generated */, CE815AA12D60DD6B00CB9114 /* AppDatesTests.swift */, - CE75F3AD2D9A89AA0024BB43 /* AppDatesMock.generated.swift */, ); path = AppDatesTests; sourceTree = ""; @@ -326,7 +334,6 @@ CE815A622D60D75200CB9114 /* Sources */, CE815A632D60D75200CB9114 /* Frameworks */, CE815A642D60D75200CB9114 /* Resources */, - F2D2F6B58295FDBB32EB70FE /* [CP] Copy Pods Resources */, CE815A9E2D60DB8A00CB9114 /* Embed Frameworks */, ); buildRules = ( @@ -463,23 +470,6 @@ shellPath = /bin/sh; shellScript = "if [[ -f \"${PODS_ROOT}/SwiftGen/bin/swiftgen\" ]]; then\n \"${PODS_ROOT}/SwiftGen/bin/swiftgen\"\nelse\n echo \"warning: SwiftGen is not installed. Run 'pod install --repo-update' to install it.\"\nfi\n"; }; - F2D2F6B58295FDBB32EB70FE /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-AppDates-AppDatesTests/Pods-App-AppDates-AppDatesTests-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-AppDates-AppDatesTests/Pods-App-AppDates-AppDatesTests-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App-AppDates-AppDatesTests/Pods-App-AppDates-AppDatesTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -510,7 +500,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - CE75F3AE2D9A89AA0024BB43 /* AppDatesMock.generated.swift in Sources */, + A5B468202F2A1101002A4ECA /* AppDatesMocks.generated.swift in Sources */, CE815AA32D60DD6B00CB9114 /* AppDatesTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/AppDates/AppDates/Data/DatesPersistenceProtocol.swift b/AppDates/AppDates/Data/DatesPersistenceProtocol.swift index 67dc358cd..dec10bf66 100644 --- a/AppDates/AppDates/Data/DatesPersistenceProtocol.swift +++ b/AppDates/AppDates/Data/DatesPersistenceProtocol.swift @@ -8,7 +8,7 @@ import Foundation import Core -//sourcery: AutoMockable +/// @mockable public protocol DatesPersistenceProtocol: Sendable { func loadCourseDates(limit: Int?, offset: Int?) async throws -> [CourseDate] func saveCourseDates(dates: [CourseDate], startIndex: Int) async @@ -16,7 +16,7 @@ public protocol DatesPersistenceProtocol: Sendable { } #if DEBUG -public struct DatesPersistenceMock: DatesPersistenceProtocol { +public struct DatesPersistencePreviewMock: DatesPersistenceProtocol { public func loadCourseDates(limit: Int?, offset: Int?) async throws -> [CourseDate] {[]} public func saveCourseDates(dates: [CourseDate], startIndex: Int) async {} public func clearAllCourseDates() async {} diff --git a/AppDates/AppDates/Data/DatesRepository.swift b/AppDates/AppDates/Data/DatesRepository.swift index e64373aeb..a73b4a508 100644 --- a/AppDates/AppDates/Data/DatesRepository.swift +++ b/AppDates/AppDates/Data/DatesRepository.swift @@ -9,6 +9,7 @@ import Foundation import Core import OEXFoundation +/// @mockable public protocol DatesRepositoryProtocol: Sendable { func getCourseDates(page: Int) async throws -> ([CourseDate], String?) func getCourseDatesOffline(limit: Int?, offset: Int?) async throws -> [CourseDate] @@ -73,7 +74,7 @@ public actor DatesRepository: DatesRepositoryProtocol { // Mark - For testing and SwiftUI preview #if DEBUG -public final class DatesRepositoryMock: DatesRepositoryProtocol { +public final class DatesRepositoryPreviewMock: DatesRepositoryProtocol { public init() {} diff --git a/AppDates/AppDates/Domain/DatesInteractor.swift b/AppDates/AppDates/Domain/DatesInteractor.swift index 772db3af0..d03c5291a 100644 --- a/AppDates/AppDates/Domain/DatesInteractor.swift +++ b/AppDates/AppDates/Domain/DatesInteractor.swift @@ -8,7 +8,7 @@ import Foundation import Core -//sourcery: AutoMockable +/// @mockable public protocol DatesInteractorProtocol: Sendable { func getCourseDates(page: Int) async throws -> ([CourseDate], String?) func getCourseDatesOffline(limit: Int?, offset: Int?) async throws -> [CourseDate] @@ -39,6 +39,6 @@ public actor DatesInteractor: DatesInteractorProtocol { // Mark - For testing and SwiftUI preview #if DEBUG public extension DatesInteractor { - static let mock = DatesInteractor(repository: DatesRepositoryMock()) + static let mock = DatesInteractor(repository: DatesRepositoryPreviewMock()) } #endif diff --git a/AppDates/AppDates/Presentation/AppDatesAnalytics.swift b/AppDates/AppDates/Presentation/AppDatesAnalytics.swift index fc58f0569..75b794525 100644 --- a/AppDates/AppDates/Presentation/AppDatesAnalytics.swift +++ b/AppDates/AppDates/Presentation/AppDatesAnalytics.swift @@ -7,8 +7,8 @@ import Foundation -//sourcery: AutoMockable -public protocol AppDatesAnalytics { +/// @mockable +public protocol AppDatesAnalytics: Sendable { func mainDatesScreenViewed() func datesCourseClicked(courseId: String, courseName: String) func datesSettingsClicked() @@ -16,7 +16,7 @@ public protocol AppDatesAnalytics { } #if DEBUG -class AppDatesAnalyticsMock: AppDatesAnalytics { +public final class `AppDatesAnalyticsPreviewMock`: AppDatesAnalytics { public func mainDatesScreenViewed() {} public func datesCourseClicked(courseId: String, courseName: String) {} public func datesSettingsClicked() {} diff --git a/AppDates/AppDates/Presentation/AppDatesRouter.swift b/AppDates/AppDates/Presentation/AppDatesRouter.swift index 4ce369f5b..4c99f76b0 100644 --- a/AppDates/AppDates/Presentation/AppDatesRouter.swift +++ b/AppDates/AppDates/Presentation/AppDatesRouter.swift @@ -8,6 +8,7 @@ import Foundation import Core +/// @mockable @MainActor public protocol AppDatesRouter: BaseRouter { func showSettings() @@ -28,7 +29,7 @@ public protocol AppDatesRouter: BaseRouter { // Mark - For testing and SwiftUI preview #if DEBUG -public class AppDatesRouterMock: BaseRouterMock, AppDatesRouter { +public class AppDatesRouterPreviewMock: BaseRouterMock, AppDatesRouter { public func showSettings() {} public func showUpdateRequiredView(showAccountLink: Bool) {} public func showCourseScreens( diff --git a/AppDates/AppDates/Presentation/Dates/DatesView.swift b/AppDates/AppDates/Presentation/Dates/DatesView.swift index fdb4036db..134a0876b 100644 --- a/AppDates/AppDates/Presentation/Dates/DatesView.swift +++ b/AppDates/AppDates/Presentation/Dates/DatesView.swift @@ -210,8 +210,8 @@ struct DatesEmptyStateView: View { interactor: DatesInteractor.mock, connectivity: Connectivity(config: ConfigMock()), courseManager: CourseStructureManagerMock(), - analytics: AppDatesAnalyticsMock(), - router: AppDatesRouterMock() + analytics: AppDatesAnalyticsPreviewMock(), + router: AppDatesRouterPreviewMock() ) ) } diff --git a/AppDates/AppDatesTests/AppDatesMock.generated.swift b/AppDates/AppDatesTests/AppDatesMock.generated.swift deleted file mode 100644 index 7eb618240..000000000 --- a/AppDates/AppDatesTests/AppDatesMock.generated.swift +++ /dev/null @@ -1,5295 +0,0 @@ -// Generated using Sourcery 2.1.2 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT - - -// Generated with SwiftyMocky 4.2.0 -// Required Sourcery: 1.8.0 - - -import SwiftyMocky -import XCTest -import Core -import AppDates -import Foundation -import SwiftUI -import Combine -import OEXFoundation - - -// MARK: - AppDatesAnalytics - -open class AppDatesAnalyticsMock: AppDatesAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func mainDatesScreenViewed() { - addInvocation(.m_mainDatesScreenViewed) - let perform = methodPerformValue(.m_mainDatesScreenViewed) as? () -> Void - perform?() - } - - open func datesCourseClicked(courseId: String, courseName: String) { - addInvocation(.m_datesCourseClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_datesCourseClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func datesSettingsClicked() { - addInvocation(.m_datesSettingsClicked) - let perform = methodPerformValue(.m_datesSettingsClicked) as? () -> Void - perform?() - } - - open func datesRefreshPulled() { - addInvocation(.m_datesRefreshPulled) - let perform = methodPerformValue(.m_datesRefreshPulled) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_mainDatesScreenViewed - case m_datesCourseClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_datesSettingsClicked - case m_datesRefreshPulled - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_mainDatesScreenViewed, .m_mainDatesScreenViewed): return .match - - case (.m_datesCourseClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_datesCourseClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_datesSettingsClicked, .m_datesSettingsClicked): return .match - - case (.m_datesRefreshPulled, .m_datesRefreshPulled): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_mainDatesScreenViewed: return 0 - case let .m_datesCourseClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case .m_datesSettingsClicked: return 0 - case .m_datesRefreshPulled: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_mainDatesScreenViewed: return ".mainDatesScreenViewed()" - case .m_datesCourseClicked__courseId_courseIdcourseName_courseName: return ".datesCourseClicked(courseId:courseName:)" - case .m_datesSettingsClicked: return ".datesSettingsClicked()" - case .m_datesRefreshPulled: return ".datesRefreshPulled()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func mainDatesScreenViewed() -> Verify { return Verify(method: .m_mainDatesScreenViewed)} - public static func datesCourseClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_datesCourseClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func datesSettingsClicked() -> Verify { return Verify(method: .m_datesSettingsClicked)} - public static func datesRefreshPulled() -> Verify { return Verify(method: .m_datesRefreshPulled)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func mainDatesScreenViewed(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_mainDatesScreenViewed, performs: perform) - } - public static func datesCourseClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_datesCourseClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func datesSettingsClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_datesSettingsClicked, performs: perform) - } - public static func datesRefreshPulled(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_datesRefreshPulled, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - AuthInteractorProtocol - -open class AuthInteractorProtocolMock: AuthInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - @discardableResult - open func login(username: String, password: String) throws -> User { - addInvocation(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) - let perform = methodPerformValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) as? (String, String) -> Void - perform?(`username`, `password`) - var __value: User - do { - __value = try methodReturnValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(username: String, password: String). Use given") - Failure("Stub return value not specified for login(username: String, password: String). Use given") - } catch { - throw error - } - return __value - } - - @discardableResult - open func login(externalToken: String, backend: String) throws -> User { - addInvocation(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) - let perform = methodPerformValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) as? (String, String) -> Void - perform?(`externalToken`, `backend`) - var __value: User - do { - __value = try methodReturnValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - Failure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - } catch { - throw error - } - return __value - } - - open func login(ssoToken: String) throws -> User { - addInvocation(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) - let perform = methodPerformValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) as? (String) -> Void - perform?(`ssoToken`) - var __value: User - do { - __value = try methodReturnValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(ssoToken: String). Use given") - Failure("Stub return value not specified for login(ssoToken: String). Use given") - } catch { - throw error - } - return __value - } - - open func resetPassword(email: String) throws -> ResetPassword { - addInvocation(.m_resetPassword__email_email(Parameter.value(`email`))) - let perform = methodPerformValue(.m_resetPassword__email_email(Parameter.value(`email`))) as? (String) -> Void - perform?(`email`) - var __value: ResetPassword - do { - __value = try methodReturnValue(.m_resetPassword__email_email(Parameter.value(`email`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for resetPassword(email: String). Use given") - Failure("Stub return value not specified for resetPassword(email: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCookies(force: Bool) throws { - addInvocation(.m_getCookies__force_force(Parameter.value(`force`))) - let perform = methodPerformValue(.m_getCookies__force_force(Parameter.value(`force`))) as? (Bool) -> Void - perform?(`force`) - do { - _ = try methodReturnValue(.m_getCookies__force_force(Parameter.value(`force`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getRegistrationFields() throws -> [PickerFields] { - addInvocation(.m_getRegistrationFields) - let perform = methodPerformValue(.m_getRegistrationFields) as? () -> Void - perform?() - var __value: [PickerFields] - do { - __value = try methodReturnValue(.m_getRegistrationFields).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getRegistrationFields(). Use given") - Failure("Stub return value not specified for getRegistrationFields(). Use given") - } catch { - throw error - } - return __value - } - - open func registerUser(fields: [String: String], isSocial: Bool) throws -> User { - addInvocation(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) - let perform = methodPerformValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) as? ([String: String], Bool) -> Void - perform?(`fields`, `isSocial`) - var __value: User - do { - __value = try methodReturnValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - Failure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - } catch { - throw error - } - return __value - } - - open func validateRegistrationFields(fields: [String: String]) throws -> [String: String] { - addInvocation(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) - let perform = methodPerformValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) as? ([String: String]) -> Void - perform?(`fields`) - var __value: [String: String] - do { - __value = try methodReturnValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - Failure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_login__username_usernamepassword_password(Parameter, Parameter) - case m_login__externalToken_externalTokenbackend_backend(Parameter, Parameter) - case m_login__ssoToken_ssoToken(Parameter) - case m_resetPassword__email_email(Parameter) - case m_getCookies__force_force(Parameter) - case m_getRegistrationFields - case m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>, Parameter) - case m_validateRegistrationFields__fields_fields(Parameter<[String: String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_login__username_usernamepassword_password(let lhsUsername, let lhsPassword), .m_login__username_usernamepassword_password(let rhsUsername, let rhsPassword)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsername, rhs: rhsUsername, with: matcher), lhsUsername, rhsUsername, "username")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPassword, rhs: rhsPassword, with: matcher), lhsPassword, rhsPassword, "password")) - return Matcher.ComparisonResult(results) - - case (.m_login__externalToken_externalTokenbackend_backend(let lhsExternaltoken, let lhsBackend), .m_login__externalToken_externalTokenbackend_backend(let rhsExternaltoken, let rhsBackend)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsExternaltoken, rhs: rhsExternaltoken, with: matcher), lhsExternaltoken, rhsExternaltoken, "externalToken")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBackend, rhs: rhsBackend, with: matcher), lhsBackend, rhsBackend, "backend")) - return Matcher.ComparisonResult(results) - - case (.m_login__ssoToken_ssoToken(let lhsSsotoken), .m_login__ssoToken_ssoToken(let rhsSsotoken)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSsotoken, rhs: rhsSsotoken, with: matcher), lhsSsotoken, rhsSsotoken, "ssoToken")) - return Matcher.ComparisonResult(results) - - case (.m_resetPassword__email_email(let lhsEmail), .m_resetPassword__email_email(let rhsEmail)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEmail, rhs: rhsEmail, with: matcher), lhsEmail, rhsEmail, "email")) - return Matcher.ComparisonResult(results) - - case (.m_getCookies__force_force(let lhsForce), .m_getCookies__force_force(let rhsForce)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsForce, rhs: rhsForce, with: matcher), lhsForce, rhsForce, "force")) - return Matcher.ComparisonResult(results) - - case (.m_getRegistrationFields, .m_getRegistrationFields): return .match - - case (.m_registerUser__fields_fieldsisSocial_isSocial(let lhsFields, let lhsIssocial), .m_registerUser__fields_fieldsisSocial_isSocial(let rhsFields, let rhsIssocial)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIssocial, rhs: rhsIssocial, with: matcher), lhsIssocial, rhsIssocial, "isSocial")) - return Matcher.ComparisonResult(results) - - case (.m_validateRegistrationFields__fields_fields(let lhsFields), .m_validateRegistrationFields__fields_fields(let rhsFields)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_login__username_usernamepassword_password(p0, p1): return p0.intValue + p1.intValue - case let .m_login__externalToken_externalTokenbackend_backend(p0, p1): return p0.intValue + p1.intValue - case let .m_login__ssoToken_ssoToken(p0): return p0.intValue - case let .m_resetPassword__email_email(p0): return p0.intValue - case let .m_getCookies__force_force(p0): return p0.intValue - case .m_getRegistrationFields: return 0 - case let .m_registerUser__fields_fieldsisSocial_isSocial(p0, p1): return p0.intValue + p1.intValue - case let .m_validateRegistrationFields__fields_fields(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_login__username_usernamepassword_password: return ".login(username:password:)" - case .m_login__externalToken_externalTokenbackend_backend: return ".login(externalToken:backend:)" - case .m_login__ssoToken_ssoToken: return ".login(ssoToken:)" - case .m_resetPassword__email_email: return ".resetPassword(email:)" - case .m_getCookies__force_force: return ".getCookies(force:)" - case .m_getRegistrationFields: return ".getRegistrationFields()" - case .m_registerUser__fields_fieldsisSocial_isSocial: return ".registerUser(fields:isSocial:)" - case .m_validateRegistrationFields__fields_fields: return ".validateRegistrationFields(fields:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - @discardableResult - public static func login(username: Parameter, password: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func login(ssoToken: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func resetPassword(email: Parameter, willReturn: ResetPassword...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getRegistrationFields(willReturn: [PickerFields]...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willReturn: [String: String]...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func login(ssoToken: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func login(ssoToken: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func resetPassword(email: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resetPassword(email: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (ResetPassword).self) - willProduce(stubber) - return given - } - public static func getCookies(force: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCookies(force: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func getRegistrationFields(willThrow: Error...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getRegistrationFields(willProduce: (StubberThrows<[PickerFields]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([PickerFields]).self) - willProduce(stubber) - return given - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willProduce: (StubberThrows<[String: String]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([String: String]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - @discardableResult - public static func login(username: Parameter, password: Parameter) -> Verify { return Verify(method: .m_login__username_usernamepassword_password(`username`, `password`))} - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter) -> Verify { return Verify(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`))} - public static func login(ssoToken: Parameter) -> Verify { return Verify(method: .m_login__ssoToken_ssoToken(`ssoToken`))} - public static func resetPassword(email: Parameter) -> Verify { return Verify(method: .m_resetPassword__email_email(`email`))} - public static func getCookies(force: Parameter) -> Verify { return Verify(method: .m_getCookies__force_force(`force`))} - public static func getRegistrationFields() -> Verify { return Verify(method: .m_getRegistrationFields)} - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter) -> Verify { return Verify(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`))} - public static func validateRegistrationFields(fields: Parameter<[String: String]>) -> Verify { return Verify(method: .m_validateRegistrationFields__fields_fields(`fields`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - @discardableResult - public static func login(username: Parameter, password: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__username_usernamepassword_password(`username`, `password`), performs: perform) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), performs: perform) - } - public static func login(ssoToken: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_login__ssoToken_ssoToken(`ssoToken`), performs: perform) - } - public static func resetPassword(email: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_resetPassword__email_email(`email`), performs: perform) - } - public static func getCookies(force: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_getCookies__force_force(`force`), performs: perform) - } - public static func getRegistrationFields(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getRegistrationFields, performs: perform) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, perform: @escaping ([String: String], Bool) -> Void) -> Perform { - return Perform(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), performs: perform) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, perform: @escaping ([String: String]) -> Void) -> Perform { - return Perform(method: .m_validateRegistrationFields__fields_fields(`fields`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - BaseRouter -@MainActor -open class BaseRouterMock: BaseRouter, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func backToRoot(animated: Bool) { - addInvocation(.m_backToRoot__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_backToRoot__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func back(animated: Bool) { - addInvocation(.m_back__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_back__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func backWithFade() { - addInvocation(.m_backWithFade) - let perform = methodPerformValue(.m_backWithFade) as? () -> Void - perform?() - } - - open func dismiss(animated: Bool) { - addInvocation(.m_dismiss__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_dismiss__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func removeLastView(controllers: Int) { - addInvocation(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) - let perform = methodPerformValue(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) as? (Int) -> Void - perform?(`controllers`) - } - - open func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { - addInvocation(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) - let perform = methodPerformValue(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) as? (LogistrationSourceScreen, PostLoginData?) -> Void - perform?(`sourceScreen`, `postLoginData`) - } - - open func showStartupScreen() { - addInvocation(.m_showStartupScreen) - let perform = methodPerformValue(.m_showStartupScreen) as? () -> Void - perform?() - } - - open func showLoginScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showForgotPasswordScreen() { - addInvocation(.m_showForgotPasswordScreen) - let perform = methodPerformValue(.m_showForgotPasswordScreen) as? () -> Void - perform?() - } - - open func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) as? (String?, LogistrationSourceScreen) -> Void - perform?(`searchQuery`, `sourceScreen`) - } - - open func showWebBrowser(title: String, url: URL) { - addInvocation(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) - let perform = methodPerformValue(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) as? (String, URL) -> Void - perform?(`title`, `url`) - } - - open func showSSOWebBrowser(title: String) { - addInvocation(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) - let perform = methodPerformValue(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) as? (String) -> Void - perform?(`title`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) as? (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void - perform?(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) as? (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void - perform?(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { - addInvocation(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) as? (UIModalTransitionStyle, any View, (() -> Void)?) -> Void - perform?(`transitionStyle`, `view`, `completion`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { - addInvocation(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) as? (UIModalTransitionStyle, Bool, () -> any View) -> Void - perform?(`transitionStyle`, `animated`, `content`) - } - - - fileprivate enum MethodType { - case m_backToRoot__animated_animated(Parameter) - case m_back__animated_animated(Parameter) - case m_backWithFade - case m_dismiss__animated_animated(Parameter) - case m_removeLastView__controllers_controllers(Parameter) - case m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter, Parameter) - case m_showStartupScreen - case m_showLoginScreen__sourceScreen_sourceScreen(Parameter) - case m_showRegisterScreen__sourceScreen_sourceScreen(Parameter) - case m_showForgotPasswordScreen - case m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter, Parameter) - case m_showWebBrowser__title_titleurl_url(Parameter, Parameter) - case m_showSSOWebBrowser__title_title(Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter<() -> Void>) - case m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter, Parameter, Parameter<(() -> Void)?>) - case m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter, Parameter, Parameter<() -> any View>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_backToRoot__animated_animated(let lhsAnimated), .m_backToRoot__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_back__animated_animated(let lhsAnimated), .m_back__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_backWithFade, .m_backWithFade): return .match - - case (.m_dismiss__animated_animated(let lhsAnimated), .m_dismiss__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_removeLastView__controllers_controllers(let lhsControllers), .m_removeLastView__controllers_controllers(let rhsControllers)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsControllers, rhs: rhsControllers, with: matcher), lhsControllers, rhsControllers, "controllers")) - return Matcher.ComparisonResult(results) - - case (.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let lhsSourcescreen, let lhsPostlogindata), .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let rhsSourcescreen, let rhsPostlogindata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPostlogindata, rhs: rhsPostlogindata, with: matcher), lhsPostlogindata, rhsPostlogindata, "postLoginData")) - return Matcher.ComparisonResult(results) - - case (.m_showStartupScreen, .m_showStartupScreen): return .match - - case (.m_showLoginScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showLoginScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showRegisterScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showRegisterScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showForgotPasswordScreen, .m_showForgotPasswordScreen): return .match - - case (.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let lhsSearchquery, let lhsSourcescreen), .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let rhsSearchquery, let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchquery, rhs: rhsSearchquery, with: matcher), lhsSearchquery, rhsSearchquery, "searchQuery")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showWebBrowser__title_titleurl_url(let lhsTitle, let lhsUrl), .m_showWebBrowser__title_titleurl_url(let rhsTitle, let rhsUrl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - return Matcher.ComparisonResult(results) - - case (.m_showSSOWebBrowser__title_title(let lhsTitle), .m_showSSOWebBrowser__title_title(let rhsTitle)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let lhsAlerttitle, let lhsAlertmessage, let lhsPositiveaction, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsType), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let rhsAlerttitle, let rhsAlertmessage, let rhsPositiveaction, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPositiveaction, rhs: rhsPositiveaction, with: matcher), lhsPositiveaction, rhsPositiveaction, "positiveAction")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let lhsAlerttitle, let lhsAlertmessage, let lhsNextsectionname, let lhsAction, let lhsImage, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsNextsectiontapped), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let rhsAlerttitle, let rhsAlertmessage, let rhsNextsectionname, let rhsAction, let rhsImage, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsNextsectiontapped)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectionname, rhs: rhsNextsectionname, with: matcher), lhsNextsectionname, rhsNextsectionname, "nextSectionName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsImage, rhs: rhsImage, with: matcher), lhsImage, rhsImage, "image")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectiontapped, rhs: rhsNextsectiontapped, with: matcher), lhsNextsectiontapped, rhsNextsectiontapped, "nextSectionTapped")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let lhsTransitionstyle, let lhsView, let lhsCompletion), .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let rhsTransitionstyle, let rhsView, let rhsCompletion)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsView, rhs: rhsView, with: matcher), lhsView, rhsView, "view")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCompletion, rhs: rhsCompletion, with: matcher), lhsCompletion, rhsCompletion, "completion")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let lhsTransitionstyle, let lhsAnimated, let lhsContent), .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let rhsTransitionstyle, let rhsAnimated, let rhsContent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsContent, rhs: rhsContent, with: matcher), lhsContent, rhsContent, "content")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_backToRoot__animated_animated(p0): return p0.intValue - case let .m_back__animated_animated(p0): return p0.intValue - case .m_backWithFade: return 0 - case let .m_dismiss__animated_animated(p0): return p0.intValue - case let .m_removeLastView__controllers_controllers(p0): return p0.intValue - case let .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(p0, p1): return p0.intValue + p1.intValue - case .m_showStartupScreen: return 0 - case let .m_showLoginScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case let .m_showRegisterScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case .m_showForgotPasswordScreen: return 0 - case let .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(p0, p1): return p0.intValue + p1.intValue - case let .m_showWebBrowser__title_titleurl_url(p0, p1): return p0.intValue + p1.intValue - case let .m_showSSOWebBrowser__title_title(p0): return p0.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(p0, p1, p2, p3, p4, p5, p6, p7): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue + p7.intValue - case let .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_backToRoot__animated_animated: return ".backToRoot(animated:)" - case .m_back__animated_animated: return ".back(animated:)" - case .m_backWithFade: return ".backWithFade()" - case .m_dismiss__animated_animated: return ".dismiss(animated:)" - case .m_removeLastView__controllers_controllers: return ".removeLastView(controllers:)" - case .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData: return ".showMainOrWhatsNewScreen(sourceScreen:postLoginData:)" - case .m_showStartupScreen: return ".showStartupScreen()" - case .m_showLoginScreen__sourceScreen_sourceScreen: return ".showLoginScreen(sourceScreen:)" - case .m_showRegisterScreen__sourceScreen_sourceScreen: return ".showRegisterScreen(sourceScreen:)" - case .m_showForgotPasswordScreen: return ".showForgotPasswordScreen()" - case .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen: return ".showDiscoveryScreen(searchQuery:sourceScreen:)" - case .m_showWebBrowser__title_titleurl_url: return ".showWebBrowser(title:url:)" - case .m_showSSOWebBrowser__title_title: return ".showSSOWebBrowser(title:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type: return ".presentAlert(alertTitle:alertMessage:positiveAction:onCloseTapped:firstButtonTapped:type:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped: return ".presentAlert(alertTitle:alertMessage:nextSectionName:action:image:onCloseTapped:firstButtonTapped:nextSectionTapped:)" - case .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion: return ".presentView(transitionStyle:view:completion:)" - case .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content: return ".presentView(transitionStyle:animated:content:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func backToRoot(animated: Parameter) -> Verify { return Verify(method: .m_backToRoot__animated_animated(`animated`))} - public static func back(animated: Parameter) -> Verify { return Verify(method: .m_back__animated_animated(`animated`))} - public static func backWithFade() -> Verify { return Verify(method: .m_backWithFade)} - public static func dismiss(animated: Parameter) -> Verify { return Verify(method: .m_dismiss__animated_animated(`animated`))} - public static func removeLastView(controllers: Parameter) -> Verify { return Verify(method: .m_removeLastView__controllers_controllers(`controllers`))} - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter) -> Verify { return Verify(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`))} - public static func showStartupScreen() -> Verify { return Verify(method: .m_showStartupScreen)} - public static func showLoginScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showRegisterScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showForgotPasswordScreen() -> Verify { return Verify(method: .m_showForgotPasswordScreen)} - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter) -> Verify { return Verify(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`))} - public static func showWebBrowser(title: Parameter, url: Parameter) -> Verify { return Verify(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`))} - public static func showSSOWebBrowser(title: Parameter) -> Verify { return Verify(method: .m_showSSOWebBrowser__title_title(`title`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`))} - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`))} - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func backToRoot(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_backToRoot__animated_animated(`animated`), performs: perform) - } - public static func back(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_back__animated_animated(`animated`), performs: perform) - } - public static func backWithFade(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_backWithFade, performs: perform) - } - public static func dismiss(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_dismiss__animated_animated(`animated`), performs: perform) - } - public static func removeLastView(controllers: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_removeLastView__controllers_controllers(`controllers`), performs: perform) - } - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter, perform: @escaping (LogistrationSourceScreen, PostLoginData?) -> Void) -> Perform { - return Perform(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`), performs: perform) - } - public static func showStartupScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showStartupScreen, performs: perform) - } - public static func showLoginScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showRegisterScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showForgotPasswordScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showForgotPasswordScreen, performs: perform) - } - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter, perform: @escaping (String?, LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`), performs: perform) - } - public static func showWebBrowser(title: Parameter, url: Parameter, perform: @escaping (String, URL) -> Void) -> Perform { - return Perform(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`), performs: perform) - } - public static func showSSOWebBrowser(title: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showSSOWebBrowser__title_title(`title`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter, perform: @escaping (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>, perform: @escaping (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>, perform: @escaping (UIModalTransitionStyle, any View, (() -> Void)?) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>, perform: @escaping (UIModalTransitionStyle, Bool, () -> any View) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CalendarManagerProtocol -@MainActor -open class CalendarManagerProtocolMock: CalendarManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func createCalendarIfNeeded() { - addInvocation(.m_createCalendarIfNeeded) - let perform = methodPerformValue(.m_createCalendarIfNeeded) as? () -> Void - perform?() - } - - open func filterCoursesBySelected(fetchedCourses: [CourseForSync]) -> [CourseForSync] { - addInvocation(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) - let perform = methodPerformValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) as? ([CourseForSync]) -> Void - perform?(`fetchedCourses`) - var __value: [CourseForSync] - do { - __value = try methodReturnValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))).casted() - } catch { - onFatalFailure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - Failure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - } - return __value - } - - open func removeOldCalendar() { - addInvocation(.m_removeOldCalendar) - let perform = methodPerformValue(.m_removeOldCalendar) as? () -> Void - perform?() - } - - open func removeOutdatedEvents(courseID: String) { - addInvocation(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - } - - open func syncCourse(courseID: String, courseName: String, dates: CourseDates) { - addInvocation(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) - let perform = methodPerformValue(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) as? (String, String, CourseDates) -> Void - perform?(`courseID`, `courseName`, `dates`) - } - - open func requestAccess() -> Bool { - addInvocation(.m_requestAccess) - let perform = methodPerformValue(.m_requestAccess) as? () -> Void - perform?() - var __value: Bool - do { - __value = try methodReturnValue(.m_requestAccess).casted() - } catch { - onFatalFailure("Stub return value not specified for requestAccess(). Use given") - Failure("Stub return value not specified for requestAccess(). Use given") - } - return __value - } - - open func courseStatus(courseID: String) -> SyncStatus { - addInvocation(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: SyncStatus - do { - __value = try methodReturnValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for courseStatus(courseID: String). Use given") - Failure("Stub return value not specified for courseStatus(courseID: String). Use given") - } - return __value - } - - open func clearAllData(removeCalendar: Bool) { - addInvocation(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) - let perform = methodPerformValue(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) as? (Bool) -> Void - perform?(`removeCalendar`) - } - - open func isDatesChanged(courseID: String, checksum: String) -> Bool { - addInvocation(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) - let perform = methodPerformValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) as? (String, String) -> Void - perform?(`courseID`, `checksum`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - Failure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - } - return __value - } - - - fileprivate enum MethodType { - case m_createCalendarIfNeeded - case m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>) - case m_removeOldCalendar - case m_removeOutdatedEvents__courseID_courseID(Parameter) - case m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter, Parameter, Parameter) - case m_requestAccess - case m_courseStatus__courseID_courseID(Parameter) - case m_clearAllData__removeCalendar_removeCalendar(Parameter) - case m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_createCalendarIfNeeded, .m_createCalendarIfNeeded): return .match - - case (.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let lhsFetchedcourses), .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let rhsFetchedcourses)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFetchedcourses, rhs: rhsFetchedcourses, with: matcher), lhsFetchedcourses, rhsFetchedcourses, "fetchedCourses")) - return Matcher.ComparisonResult(results) - - case (.m_removeOldCalendar, .m_removeOldCalendar): return .match - - case (.m_removeOutdatedEvents__courseID_courseID(let lhsCourseid), .m_removeOutdatedEvents__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let lhsCourseid, let lhsCoursename, let lhsDates), .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let rhsCourseid, let rhsCoursename, let rhsDates)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDates, rhs: rhsDates, with: matcher), lhsDates, rhsDates, "dates")) - return Matcher.ComparisonResult(results) - - case (.m_requestAccess, .m_requestAccess): return .match - - case (.m_courseStatus__courseID_courseID(let lhsCourseid), .m_courseStatus__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_clearAllData__removeCalendar_removeCalendar(let lhsRemovecalendar), .m_clearAllData__removeCalendar_removeCalendar(let rhsRemovecalendar)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRemovecalendar, rhs: rhsRemovecalendar, with: matcher), lhsRemovecalendar, rhsRemovecalendar, "removeCalendar")) - return Matcher.ComparisonResult(results) - - case (.m_isDatesChanged__courseID_courseIDchecksum_checksum(let lhsCourseid, let lhsChecksum), .m_isDatesChanged__courseID_courseIDchecksum_checksum(let rhsCourseid, let rhsChecksum)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsChecksum, rhs: rhsChecksum, with: matcher), lhsChecksum, rhsChecksum, "checksum")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_createCalendarIfNeeded: return 0 - case let .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(p0): return p0.intValue - case .m_removeOldCalendar: return 0 - case let .m_removeOutdatedEvents__courseID_courseID(p0): return p0.intValue - case let .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case .m_requestAccess: return 0 - case let .m_courseStatus__courseID_courseID(p0): return p0.intValue - case let .m_clearAllData__removeCalendar_removeCalendar(p0): return p0.intValue - case let .m_isDatesChanged__courseID_courseIDchecksum_checksum(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_createCalendarIfNeeded: return ".createCalendarIfNeeded()" - case .m_filterCoursesBySelected__fetchedCourses_fetchedCourses: return ".filterCoursesBySelected(fetchedCourses:)" - case .m_removeOldCalendar: return ".removeOldCalendar()" - case .m_removeOutdatedEvents__courseID_courseID: return ".removeOutdatedEvents(courseID:)" - case .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates: return ".syncCourse(courseID:courseName:dates:)" - case .m_requestAccess: return ".requestAccess()" - case .m_courseStatus__courseID_courseID: return ".courseStatus(courseID:)" - case .m_clearAllData__removeCalendar_removeCalendar: return ".clearAllData(removeCalendar:)" - case .m_isDatesChanged__courseID_courseIDchecksum_checksum: return ".isDatesChanged(courseID:checksum:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willReturn: [CourseForSync]...) -> MethodStub { - return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func requestAccess(willReturn: Bool...) -> MethodStub { - return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func courseStatus(courseID: Parameter, willReturn: SyncStatus...) -> MethodStub { - return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willProduce: (Stubber<[CourseForSync]>) -> Void) -> MethodStub { - let willReturn: [[CourseForSync]] = [] - let given: Given = { return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([CourseForSync]).self) - willProduce(stubber) - return given - } - public static func requestAccess(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func courseStatus(courseID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [SyncStatus] = [] - let given: Given = { return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (SyncStatus).self) - willProduce(stubber) - return given - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func createCalendarIfNeeded() -> Verify { return Verify(method: .m_createCalendarIfNeeded)} - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>) -> Verify { return Verify(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`))} - public static func removeOldCalendar() -> Verify { return Verify(method: .m_removeOldCalendar)} - public static func removeOutdatedEvents(courseID: Parameter) -> Verify { return Verify(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`))} - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter) -> Verify { return Verify(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`))} - public static func requestAccess() -> Verify { return Verify(method: .m_requestAccess)} - public static func courseStatus(courseID: Parameter) -> Verify { return Verify(method: .m_courseStatus__courseID_courseID(`courseID`))} - public static func clearAllData(removeCalendar: Parameter) -> Verify { return Verify(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`))} - public static func isDatesChanged(courseID: Parameter, checksum: Parameter) -> Verify { return Verify(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func createCalendarIfNeeded(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_createCalendarIfNeeded, performs: perform) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, perform: @escaping ([CourseForSync]) -> Void) -> Perform { - return Perform(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), performs: perform) - } - public static func removeOldCalendar(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeOldCalendar, performs: perform) - } - public static func removeOutdatedEvents(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`), performs: perform) - } - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter, perform: @escaping (String, String, CourseDates) -> Void) -> Perform { - return Perform(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`), performs: perform) - } - public static func requestAccess(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_requestAccess, performs: perform) - } - public static func courseStatus(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_courseStatus__courseID_courseID(`courseID`), performs: perform) - } - public static func clearAllData(removeCalendar: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`), performs: perform) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConfigProtocol - -open class ConfigProtocolMock: ConfigProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var baseURL: URL { - get { invocations.append(.p_baseURL_get); return __p_baseURL ?? givenGetterValue(.p_baseURL_get, "ConfigProtocolMock - stub value for baseURL was not defined") } - } - private var __p_baseURL: (URL)? - - public var baseSSOURL: URL { - get { invocations.append(.p_baseSSOURL_get); return __p_baseSSOURL ?? givenGetterValue(.p_baseSSOURL_get, "ConfigProtocolMock - stub value for baseSSOURL was not defined") } - } - private var __p_baseSSOURL: (URL)? - - public var ssoFinishedURL: URL { - get { invocations.append(.p_ssoFinishedURL_get); return __p_ssoFinishedURL ?? givenGetterValue(.p_ssoFinishedURL_get, "ConfigProtocolMock - stub value for ssoFinishedURL was not defined") } - } - private var __p_ssoFinishedURL: (URL)? - - public var ssoButtonTitle: [String: Any] { - get { invocations.append(.p_ssoButtonTitle_get); return __p_ssoButtonTitle ?? givenGetterValue(.p_ssoButtonTitle_get, "ConfigProtocolMock - stub value for ssoButtonTitle was not defined") } - } - private var __p_ssoButtonTitle: ([String: Any])? - - public var oAuthClientId: String { - get { invocations.append(.p_oAuthClientId_get); return __p_oAuthClientId ?? givenGetterValue(.p_oAuthClientId_get, "ConfigProtocolMock - stub value for oAuthClientId was not defined") } - } - private var __p_oAuthClientId: (String)? - - public var tokenType: TokenType { - get { invocations.append(.p_tokenType_get); return __p_tokenType ?? givenGetterValue(.p_tokenType_get, "ConfigProtocolMock - stub value for tokenType was not defined") } - } - private var __p_tokenType: (TokenType)? - - public var feedbackEmail: String { - get { invocations.append(.p_feedbackEmail_get); return __p_feedbackEmail ?? givenGetterValue(.p_feedbackEmail_get, "ConfigProtocolMock - stub value for feedbackEmail was not defined") } - } - private var __p_feedbackEmail: (String)? - - public var appStoreLink: String { - get { invocations.append(.p_appStoreLink_get); return __p_appStoreLink ?? givenGetterValue(.p_appStoreLink_get, "ConfigProtocolMock - stub value for appStoreLink was not defined") } - } - private var __p_appStoreLink: (String)? - - public var faq: URL? { - get { invocations.append(.p_faq_get); return __p_faq ?? optionalGivenGetterValue(.p_faq_get, "ConfigProtocolMock - stub value for faq was not defined") } - } - private var __p_faq: (URL)? - - public var platformName: String { - get { invocations.append(.p_platformName_get); return __p_platformName ?? givenGetterValue(.p_platformName_get, "ConfigProtocolMock - stub value for platformName was not defined") } - } - private var __p_platformName: (String)? - - public var agreement: AgreementConfig { - get { invocations.append(.p_agreement_get); return __p_agreement ?? givenGetterValue(.p_agreement_get, "ConfigProtocolMock - stub value for agreement was not defined") } - } - private var __p_agreement: (AgreementConfig)? - - public var firebase: FirebaseConfig { - get { invocations.append(.p_firebase_get); return __p_firebase ?? givenGetterValue(.p_firebase_get, "ConfigProtocolMock - stub value for firebase was not defined") } - } - private var __p_firebase: (FirebaseConfig)? - - public var facebook: FacebookConfig { - get { invocations.append(.p_facebook_get); return __p_facebook ?? givenGetterValue(.p_facebook_get, "ConfigProtocolMock - stub value for facebook was not defined") } - } - private var __p_facebook: (FacebookConfig)? - - public var microsoft: MicrosoftConfig { - get { invocations.append(.p_microsoft_get); return __p_microsoft ?? givenGetterValue(.p_microsoft_get, "ConfigProtocolMock - stub value for microsoft was not defined") } - } - private var __p_microsoft: (MicrosoftConfig)? - - public var google: GoogleConfig { - get { invocations.append(.p_google_get); return __p_google ?? givenGetterValue(.p_google_get, "ConfigProtocolMock - stub value for google was not defined") } - } - private var __p_google: (GoogleConfig)? - - public var appleSignIn: AppleSignInConfig { - get { invocations.append(.p_appleSignIn_get); return __p_appleSignIn ?? givenGetterValue(.p_appleSignIn_get, "ConfigProtocolMock - stub value for appleSignIn was not defined") } - } - private var __p_appleSignIn: (AppleSignInConfig)? - - public var features: FeaturesConfig { - get { invocations.append(.p_features_get); return __p_features ?? givenGetterValue(.p_features_get, "ConfigProtocolMock - stub value for features was not defined") } - } - private var __p_features: (FeaturesConfig)? - - public var theme: ThemeConfig { - get { invocations.append(.p_theme_get); return __p_theme ?? givenGetterValue(.p_theme_get, "ConfigProtocolMock - stub value for theme was not defined") } - } - private var __p_theme: (ThemeConfig)? - - public var uiComponents: UIComponentsConfig { - get { invocations.append(.p_uiComponents_get); return __p_uiComponents ?? givenGetterValue(.p_uiComponents_get, "ConfigProtocolMock - stub value for uiComponents was not defined") } - } - private var __p_uiComponents: (UIComponentsConfig)? - - public var discovery: DiscoveryConfig { - get { invocations.append(.p_discovery_get); return __p_discovery ?? givenGetterValue(.p_discovery_get, "ConfigProtocolMock - stub value for discovery was not defined") } - } - private var __p_discovery: (DiscoveryConfig)? - - public var dashboard: DashboardConfig { - get { invocations.append(.p_dashboard_get); return __p_dashboard ?? givenGetterValue(.p_dashboard_get, "ConfigProtocolMock - stub value for dashboard was not defined") } - } - private var __p_dashboard: (DashboardConfig)? - - public var braze: BrazeConfig { - get { invocations.append(.p_braze_get); return __p_braze ?? givenGetterValue(.p_braze_get, "ConfigProtocolMock - stub value for braze was not defined") } - } - private var __p_braze: (BrazeConfig)? - - public var branch: BranchConfig { - get { invocations.append(.p_branch_get); return __p_branch ?? givenGetterValue(.p_branch_get, "ConfigProtocolMock - stub value for branch was not defined") } - } - private var __p_branch: (BranchConfig)? - - public var program: DiscoveryConfig { - get { invocations.append(.p_program_get); return __p_program ?? givenGetterValue(.p_program_get, "ConfigProtocolMock - stub value for program was not defined") } - } - private var __p_program: (DiscoveryConfig)? - - public var experimentalFeatures: ExperimentalFeaturesConfig { - get { invocations.append(.p_experimentalFeatures_get); return __p_experimentalFeatures ?? givenGetterValue(.p_experimentalFeatures_get, "ConfigProtocolMock - stub value for experimentalFeatures was not defined") } - } - private var __p_experimentalFeatures: (ExperimentalFeaturesConfig)? - - public var URIScheme: String { - get { invocations.append(.p_URIScheme_get); return __p_URIScheme ?? givenGetterValue(.p_URIScheme_get, "ConfigProtocolMock - stub value for URIScheme was not defined") } - } - private var __p_URIScheme: (String)? - - - - - - - fileprivate enum MethodType { - case p_baseURL_get - case p_baseSSOURL_get - case p_ssoFinishedURL_get - case p_ssoButtonTitle_get - case p_oAuthClientId_get - case p_tokenType_get - case p_feedbackEmail_get - case p_appStoreLink_get - case p_faq_get - case p_platformName_get - case p_agreement_get - case p_firebase_get - case p_facebook_get - case p_microsoft_get - case p_google_get - case p_appleSignIn_get - case p_features_get - case p_theme_get - case p_uiComponents_get - case p_discovery_get - case p_dashboard_get - case p_braze_get - case p_branch_get - case p_program_get - case p_experimentalFeatures_get - case p_URIScheme_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_baseURL_get,.p_baseURL_get): return Matcher.ComparisonResult.match - case (.p_baseSSOURL_get,.p_baseSSOURL_get): return Matcher.ComparisonResult.match - case (.p_ssoFinishedURL_get,.p_ssoFinishedURL_get): return Matcher.ComparisonResult.match - case (.p_ssoButtonTitle_get,.p_ssoButtonTitle_get): return Matcher.ComparisonResult.match - case (.p_oAuthClientId_get,.p_oAuthClientId_get): return Matcher.ComparisonResult.match - case (.p_tokenType_get,.p_tokenType_get): return Matcher.ComparisonResult.match - case (.p_feedbackEmail_get,.p_feedbackEmail_get): return Matcher.ComparisonResult.match - case (.p_appStoreLink_get,.p_appStoreLink_get): return Matcher.ComparisonResult.match - case (.p_faq_get,.p_faq_get): return Matcher.ComparisonResult.match - case (.p_platformName_get,.p_platformName_get): return Matcher.ComparisonResult.match - case (.p_agreement_get,.p_agreement_get): return Matcher.ComparisonResult.match - case (.p_firebase_get,.p_firebase_get): return Matcher.ComparisonResult.match - case (.p_facebook_get,.p_facebook_get): return Matcher.ComparisonResult.match - case (.p_microsoft_get,.p_microsoft_get): return Matcher.ComparisonResult.match - case (.p_google_get,.p_google_get): return Matcher.ComparisonResult.match - case (.p_appleSignIn_get,.p_appleSignIn_get): return Matcher.ComparisonResult.match - case (.p_features_get,.p_features_get): return Matcher.ComparisonResult.match - case (.p_theme_get,.p_theme_get): return Matcher.ComparisonResult.match - case (.p_uiComponents_get,.p_uiComponents_get): return Matcher.ComparisonResult.match - case (.p_discovery_get,.p_discovery_get): return Matcher.ComparisonResult.match - case (.p_dashboard_get,.p_dashboard_get): return Matcher.ComparisonResult.match - case (.p_braze_get,.p_braze_get): return Matcher.ComparisonResult.match - case (.p_branch_get,.p_branch_get): return Matcher.ComparisonResult.match - case (.p_program_get,.p_program_get): return Matcher.ComparisonResult.match - case (.p_experimentalFeatures_get,.p_experimentalFeatures_get): return Matcher.ComparisonResult.match - case (.p_URIScheme_get,.p_URIScheme_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_baseURL_get: return 0 - case .p_baseSSOURL_get: return 0 - case .p_ssoFinishedURL_get: return 0 - case .p_ssoButtonTitle_get: return 0 - case .p_oAuthClientId_get: return 0 - case .p_tokenType_get: return 0 - case .p_feedbackEmail_get: return 0 - case .p_appStoreLink_get: return 0 - case .p_faq_get: return 0 - case .p_platformName_get: return 0 - case .p_agreement_get: return 0 - case .p_firebase_get: return 0 - case .p_facebook_get: return 0 - case .p_microsoft_get: return 0 - case .p_google_get: return 0 - case .p_appleSignIn_get: return 0 - case .p_features_get: return 0 - case .p_theme_get: return 0 - case .p_uiComponents_get: return 0 - case .p_discovery_get: return 0 - case .p_dashboard_get: return 0 - case .p_braze_get: return 0 - case .p_branch_get: return 0 - case .p_program_get: return 0 - case .p_experimentalFeatures_get: return 0 - case .p_URIScheme_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_baseURL_get: return "[get] .baseURL" - case .p_baseSSOURL_get: return "[get] .baseSSOURL" - case .p_ssoFinishedURL_get: return "[get] .ssoFinishedURL" - case .p_ssoButtonTitle_get: return "[get] .ssoButtonTitle" - case .p_oAuthClientId_get: return "[get] .oAuthClientId" - case .p_tokenType_get: return "[get] .tokenType" - case .p_feedbackEmail_get: return "[get] .feedbackEmail" - case .p_appStoreLink_get: return "[get] .appStoreLink" - case .p_faq_get: return "[get] .faq" - case .p_platformName_get: return "[get] .platformName" - case .p_agreement_get: return "[get] .agreement" - case .p_firebase_get: return "[get] .firebase" - case .p_facebook_get: return "[get] .facebook" - case .p_microsoft_get: return "[get] .microsoft" - case .p_google_get: return "[get] .google" - case .p_appleSignIn_get: return "[get] .appleSignIn" - case .p_features_get: return "[get] .features" - case .p_theme_get: return "[get] .theme" - case .p_uiComponents_get: return "[get] .uiComponents" - case .p_discovery_get: return "[get] .discovery" - case .p_dashboard_get: return "[get] .dashboard" - case .p_braze_get: return "[get] .braze" - case .p_branch_get: return "[get] .branch" - case .p_program_get: return "[get] .program" - case .p_experimentalFeatures_get: return "[get] .experimentalFeatures" - case .p_URIScheme_get: return "[get] .URIScheme" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func baseURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func baseSSOURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseSSOURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoFinishedURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_ssoFinishedURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoButtonTitle(getter defaultValue: [String: Any]...) -> PropertyStub { - return Given(method: .p_ssoButtonTitle_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func oAuthClientId(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_oAuthClientId_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func tokenType(getter defaultValue: TokenType...) -> PropertyStub { - return Given(method: .p_tokenType_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func feedbackEmail(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_feedbackEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appStoreLink(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_appStoreLink_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func faq(getter defaultValue: URL?...) -> PropertyStub { - return Given(method: .p_faq_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func platformName(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_platformName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func agreement(getter defaultValue: AgreementConfig...) -> PropertyStub { - return Given(method: .p_agreement_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func firebase(getter defaultValue: FirebaseConfig...) -> PropertyStub { - return Given(method: .p_firebase_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func facebook(getter defaultValue: FacebookConfig...) -> PropertyStub { - return Given(method: .p_facebook_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func microsoft(getter defaultValue: MicrosoftConfig...) -> PropertyStub { - return Given(method: .p_microsoft_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func google(getter defaultValue: GoogleConfig...) -> PropertyStub { - return Given(method: .p_google_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignIn(getter defaultValue: AppleSignInConfig...) -> PropertyStub { - return Given(method: .p_appleSignIn_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func features(getter defaultValue: FeaturesConfig...) -> PropertyStub { - return Given(method: .p_features_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func theme(getter defaultValue: ThemeConfig...) -> PropertyStub { - return Given(method: .p_theme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func uiComponents(getter defaultValue: UIComponentsConfig...) -> PropertyStub { - return Given(method: .p_uiComponents_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func discovery(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_discovery_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func dashboard(getter defaultValue: DashboardConfig...) -> PropertyStub { - return Given(method: .p_dashboard_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func braze(getter defaultValue: BrazeConfig...) -> PropertyStub { - return Given(method: .p_braze_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func branch(getter defaultValue: BranchConfig...) -> PropertyStub { - return Given(method: .p_branch_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func program(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_program_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func experimentalFeatures(getter defaultValue: ExperimentalFeaturesConfig...) -> PropertyStub { - return Given(method: .p_experimentalFeatures_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func URIScheme(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_URIScheme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var baseURL: Verify { return Verify(method: .p_baseURL_get) } - public static var baseSSOURL: Verify { return Verify(method: .p_baseSSOURL_get) } - public static var ssoFinishedURL: Verify { return Verify(method: .p_ssoFinishedURL_get) } - public static var ssoButtonTitle: Verify { return Verify(method: .p_ssoButtonTitle_get) } - public static var oAuthClientId: Verify { return Verify(method: .p_oAuthClientId_get) } - public static var tokenType: Verify { return Verify(method: .p_tokenType_get) } - public static var feedbackEmail: Verify { return Verify(method: .p_feedbackEmail_get) } - public static var appStoreLink: Verify { return Verify(method: .p_appStoreLink_get) } - public static var faq: Verify { return Verify(method: .p_faq_get) } - public static var platformName: Verify { return Verify(method: .p_platformName_get) } - public static var agreement: Verify { return Verify(method: .p_agreement_get) } - public static var firebase: Verify { return Verify(method: .p_firebase_get) } - public static var facebook: Verify { return Verify(method: .p_facebook_get) } - public static var microsoft: Verify { return Verify(method: .p_microsoft_get) } - public static var google: Verify { return Verify(method: .p_google_get) } - public static var appleSignIn: Verify { return Verify(method: .p_appleSignIn_get) } - public static var features: Verify { return Verify(method: .p_features_get) } - public static var theme: Verify { return Verify(method: .p_theme_get) } - public static var uiComponents: Verify { return Verify(method: .p_uiComponents_get) } - public static var discovery: Verify { return Verify(method: .p_discovery_get) } - public static var dashboard: Verify { return Verify(method: .p_dashboard_get) } - public static var braze: Verify { return Verify(method: .p_braze_get) } - public static var branch: Verify { return Verify(method: .p_branch_get) } - public static var program: Verify { return Verify(method: .p_program_get) } - public static var experimentalFeatures: Verify { return Verify(method: .p_experimentalFeatures_get) } - public static var URIScheme: Verify { return Verify(method: .p_URIScheme_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConnectivityProtocol -@MainActor -open class ConnectivityProtocolMock: ConnectivityProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var isInternetAvaliable: Bool { - get { invocations.append(.p_isInternetAvaliable_get); return __p_isInternetAvaliable ?? givenGetterValue(.p_isInternetAvaliable_get, "ConnectivityProtocolMock - stub value for isInternetAvaliable was not defined") } - } - private var __p_isInternetAvaliable: (Bool)? - - public var isMobileData: Bool { - get { invocations.append(.p_isMobileData_get); return __p_isMobileData ?? givenGetterValue(.p_isMobileData_get, "ConnectivityProtocolMock - stub value for isMobileData was not defined") } - } - private var __p_isMobileData: (Bool)? - - public var internetReachableSubject: CurrentValueSubject { - get { invocations.append(.p_internetReachableSubject_get); return __p_internetReachableSubject ?? givenGetterValue(.p_internetReachableSubject_get, "ConnectivityProtocolMock - stub value for internetReachableSubject was not defined") } - } - private var __p_internetReachableSubject: (CurrentValueSubject)? - - - - - - - fileprivate enum MethodType { - case p_isInternetAvaliable_get - case p_isMobileData_get - case p_internetReachableSubject_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_isInternetAvaliable_get,.p_isInternetAvaliable_get): return Matcher.ComparisonResult.match - case (.p_isMobileData_get,.p_isMobileData_get): return Matcher.ComparisonResult.match - case (.p_internetReachableSubject_get,.p_internetReachableSubject_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_isInternetAvaliable_get: return 0 - case .p_isMobileData_get: return 0 - case .p_internetReachableSubject_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_isInternetAvaliable_get: return "[get] .isInternetAvaliable" - case .p_isMobileData_get: return "[get] .isMobileData" - case .p_internetReachableSubject_get: return "[get] .internetReachableSubject" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func isInternetAvaliable(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isInternetAvaliable_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func isMobileData(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isMobileData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func internetReachableSubject(getter defaultValue: CurrentValueSubject...) -> PropertyStub { - return Given(method: .p_internetReachableSubject_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var isInternetAvaliable: Verify { return Verify(method: .p_isInternetAvaliable_get) } - public static var isMobileData: Verify { return Verify(method: .p_isMobileData_get) } - public static var internetReachableSubject: Verify { return Verify(method: .p_internetReachableSubject_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreAnalytics - -open class CoreAnalyticsMock: CoreAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { - addInvocation(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) - let perform = methodPerformValue(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) as? (AnalyticsEvent, EventBIValue, String?, Int?) -> Void - perform?(`event`, `biValue`, `action`, `rating`) - } - - open func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { - addInvocation(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) - let perform = methodPerformValue(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) as? (AnalyticsEvent, EventBIValue, String, String) -> Void - perform?(`event`, `bivalue`, `value`, `oldValue`) - } - - open func trackEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackScreenEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackScreenEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - - fileprivate enum MethodType { - case m_trackEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter, Parameter, Parameter, Parameter) - case m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter, Parameter, Parameter, Parameter) - case m_trackEvent__event(Parameter) - case m_trackEvent__eventbiValue_biValue(Parameter, Parameter) - case m_trackScreenEvent__event(Parameter) - case m_trackScreenEvent__eventbiValue_biValue(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_trackEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackScreenEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_appreview__eventbiValue_biValueaction_actionrating_rating(let lhsEvent, let lhsBivalue, let lhsAction, let lhsRating), .m_appreview__eventbiValue_biValueaction_actionrating_rating(let rhsEvent, let rhsBivalue, let rhsAction, let rhsRating)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRating, rhs: rhsRating, with: matcher), lhsRating, rhsRating, "rating")) - return Matcher.ComparisonResult(results) - - case (.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let lhsEvent, let lhsBivalue, let lhsValue, let lhsOldvalue), .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let rhsEvent, let rhsBivalue, let rhsValue, let rhsOldvalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "bivalue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsValue, rhs: rhsValue, with: matcher), lhsValue, rhsValue, "value")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOldvalue, rhs: rhsOldvalue, with: matcher), lhsOldvalue, rhsOldvalue, "oldValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__event(let lhsEvent), .m_trackEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__event(let lhsEvent), .m_trackScreenEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackScreenEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_trackEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_trackScreenEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_appreview__eventbiValue_biValueaction_actionrating_rating(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_trackEvent__event(p0): return p0.intValue - case let .m_trackEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__event(p0): return p0.intValue - case let .m_trackScreenEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_trackEvent__eventparameters_parameters: return ".trackEvent(_:parameters:)" - case .m_trackEvent__eventbiValue_biValueparameters_parameters: return ".trackEvent(_:biValue:parameters:)" - case .m_trackScreenEvent__eventparameters_parameters: return ".trackScreenEvent(_:parameters:)" - case .m_trackScreenEvent__eventbiValue_biValueparameters_parameters: return ".trackScreenEvent(_:biValue:parameters:)" - case .m_appreview__eventbiValue_biValueaction_actionrating_rating: return ".appreview(_:biValue:action:rating:)" - case .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue: return ".videoQualityChanged(_:bivalue:value:oldValue:)" - case .m_trackEvent__event: return ".trackEvent(_:)" - case .m_trackEvent__eventbiValue_biValue: return ".trackEvent(_:biValue:)" - case .m_trackScreenEvent__event: return ".trackScreenEvent(_:)" - case .m_trackScreenEvent__eventbiValue_biValue: return ".trackScreenEvent(_:biValue:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter) -> Verify { return Verify(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`))} - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter) -> Verify { return Verify(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`))} - public static func trackEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackEvent__event(`event`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`))} - public static func trackScreenEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__event(`event`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String?, Int?) -> Void) -> Perform { - return Perform(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`), performs: perform) - } - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String, String) -> Void) -> Perform { - return Perform(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`), performs: perform) - } - public static func trackEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackEvent__event(`event`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__event(`event`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CorePersistenceProtocol - -open class CorePersistenceProtocolMock: CorePersistenceProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func set(userId: Int) { - addInvocation(.m_set__userId_userId(Parameter.value(`userId`))) - let perform = methodPerformValue(.m_set__userId_userId(Parameter.value(`userId`))) as? (Int) -> Void - perform?(`userId`) - } - - open func getUserID() -> Int? { - addInvocation(.m_getUserID) - let perform = methodPerformValue(.m_getUserID) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getUserID).casted() - } catch { - // do nothing - } - return __value - } - - @MainActor - open func publisher() throws -> AnyPublisher { - addInvocation(.m_publisher) - let perform = methodPerformValue(.m_publisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_publisher).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for publisher(). Use given") - Failure("Stub return value not specified for publisher(). Use given") - } catch { - throw error - } - return __value - } - - open func addToDownloadQueue(tasks: [DownloadDataTask]) { - addInvocation(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) as? ([DownloadDataTask]) -> Void - perform?(`tasks`) - } - - open func saveOfflineProgress(progress: OfflineProgress) { - addInvocation(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) - let perform = methodPerformValue(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) as? (OfflineProgress) -> Void - perform?(`progress`) - } - - open func loadProgress(for blockID: String) -> OfflineProgress? { - addInvocation(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - var __value: OfflineProgress? = nil - do { - __value = try methodReturnValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))).casted() - } catch { - // do nothing - } - return __value - } - - open func loadAllOfflineProgress() -> [OfflineProgress] { - addInvocation(.m_loadAllOfflineProgress) - let perform = methodPerformValue(.m_loadAllOfflineProgress) as? () -> Void - perform?() - var __value: [OfflineProgress] - do { - __value = try methodReturnValue(.m_loadAllOfflineProgress).casted() - } catch { - onFatalFailure("Stub return value not specified for loadAllOfflineProgress(). Use given") - Failure("Stub return value not specified for loadAllOfflineProgress(). Use given") - } - return __value - } - - open func deleteProgress(for blockID: String) { - addInvocation(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - } - - open func deleteAllProgress() { - addInvocation(.m_deleteAllProgress) - let perform = methodPerformValue(.m_deleteAllProgress) as? () -> Void - perform?() - } - - open func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { - addInvocation(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) as? ([CourseBlock], DownloadQuality) -> Void - perform?(`blocks`, `downloadQuality`) - } - - open func updateTask(task: DownloadDataTask) { - addInvocation(.m_updateTask__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_updateTask__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - } - - open func downloadDataTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getDownloadDataTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasks) - let perform = methodPerformValue(.m_getDownloadDataTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasks(). Use given") - Failure("Stub return value not specified for getDownloadDataTasks(). Use given") - } - return __value - } - - open func getDownloadDataTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func deleteDownloadDataTasks(ids: [String]) { - addInvocation(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) - let perform = methodPerformValue(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) as? ([String]) -> Void - perform?(`ids`) - } - - - fileprivate enum MethodType { - case m_set__userId_userId(Parameter) - case m_getUserID - case m_publisher - case m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>) - case m_saveOfflineProgress__progress_progress(Parameter) - case m_loadProgress__for_blockID(Parameter) - case m_loadAllOfflineProgress - case m_deleteProgress__for_blockID(Parameter) - case m_deleteAllProgress - case m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>, Parameter) - case m_updateTask__task_task(Parameter) - case m_downloadDataTask__for_blockId(Parameter) - case m_getDownloadDataTasks - case m_getDownloadDataTasksForCourse__courseId(Parameter) - case m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_set__userId_userId(let lhsUserid), .m_set__userId_userId(let rhsUserid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUserid, rhs: rhsUserid, with: matcher), lhsUserid, rhsUserid, "userId")) - return Matcher.ComparisonResult(results) - - case (.m_getUserID, .m_getUserID): return .match - - case (.m_publisher, .m_publisher): return .match - - case (.m_addToDownloadQueue__tasks_tasks(let lhsTasks), .m_addToDownloadQueue__tasks_tasks(let rhsTasks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTasks, rhs: rhsTasks, with: matcher), lhsTasks, rhsTasks, "tasks")) - return Matcher.ComparisonResult(results) - - case (.m_saveOfflineProgress__progress_progress(let lhsProgress), .m_saveOfflineProgress__progress_progress(let rhsProgress)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsProgress, rhs: rhsProgress, with: matcher), lhsProgress, rhsProgress, "progress")) - return Matcher.ComparisonResult(results) - - case (.m_loadProgress__for_blockID(let lhsBlockid), .m_loadProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_loadAllOfflineProgress, .m_loadAllOfflineProgress): return .match - - case (.m_deleteProgress__for_blockID(let lhsBlockid), .m_deleteProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_deleteAllProgress, .m_deleteAllProgress): return .match - - case (.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let lhsBlocks, let lhsDownloadquality), .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let rhsBlocks, let rhsDownloadquality)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadquality, rhs: rhsDownloadquality, with: matcher), lhsDownloadquality, rhsDownloadquality, "downloadQuality")) - return Matcher.ComparisonResult(results) - - case (.m_updateTask__task_task(let lhsTask), .m_updateTask__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_downloadDataTask__for_blockId(let lhsBlockid), .m_downloadDataTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadDataTasks, .m_getDownloadDataTasks): return .match - - case (.m_getDownloadDataTasksForCourse__courseId(let lhsCourseid), .m_getDownloadDataTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_deleteDownloadDataTasks__ids_ids(let lhsIds), .m_deleteDownloadDataTasks__ids_ids(let rhsIds)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIds, rhs: rhsIds, with: matcher), lhsIds, rhsIds, "ids")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_set__userId_userId(p0): return p0.intValue - case .m_getUserID: return 0 - case .m_publisher: return 0 - case let .m_addToDownloadQueue__tasks_tasks(p0): return p0.intValue - case let .m_saveOfflineProgress__progress_progress(p0): return p0.intValue - case let .m_loadProgress__for_blockID(p0): return p0.intValue - case .m_loadAllOfflineProgress: return 0 - case let .m_deleteProgress__for_blockID(p0): return p0.intValue - case .m_deleteAllProgress: return 0 - case let .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(p0, p1): return p0.intValue + p1.intValue - case let .m_updateTask__task_task(p0): return p0.intValue - case let .m_downloadDataTask__for_blockId(p0): return p0.intValue - case .m_getDownloadDataTasks: return 0 - case let .m_getDownloadDataTasksForCourse__courseId(p0): return p0.intValue - case let .m_deleteDownloadDataTasks__ids_ids(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_set__userId_userId: return ".set(userId:)" - case .m_getUserID: return ".getUserID()" - case .m_publisher: return ".publisher()" - case .m_addToDownloadQueue__tasks_tasks: return ".addToDownloadQueue(tasks:)" - case .m_saveOfflineProgress__progress_progress: return ".saveOfflineProgress(progress:)" - case .m_loadProgress__for_blockID: return ".loadProgress(for:)" - case .m_loadAllOfflineProgress: return ".loadAllOfflineProgress()" - case .m_deleteProgress__for_blockID: return ".deleteProgress(for:)" - case .m_deleteAllProgress: return ".deleteAllProgress()" - case .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality: return ".addToDownloadQueue(blocks:downloadQuality:)" - case .m_updateTask__task_task: return ".updateTask(task:)" - case .m_downloadDataTask__for_blockId: return ".downloadDataTask(for:)" - case .m_getDownloadDataTasks: return ".getDownloadDataTasks()" - case .m_getDownloadDataTasksForCourse__courseId: return ".getDownloadDataTasksForCourse(_:)" - case .m_deleteDownloadDataTasks__ids_ids: return ".deleteDownloadDataTasks(ids:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getUserID(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @MainActor - public static func publisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_publisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadProgress(for blockID: Parameter, willReturn: OfflineProgress?...) -> MethodStub { - return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadAllOfflineProgress(willReturn: [OfflineProgress]...) -> MethodStub { - return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadDataTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getUserID(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func loadProgress(for blockID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [OfflineProgress?] = [] - let given: Given = { return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (OfflineProgress?).self) - willProduce(stubber) - return given - } - public static func loadAllOfflineProgress(willProduce: (Stubber<[OfflineProgress]>) -> Void) -> MethodStub { - let willReturn: [[OfflineProgress]] = [] - let given: Given = { return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([OfflineProgress]).self) - willProduce(stubber) - return given - } - public static func downloadDataTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - @MainActor - public static func publisher(willThrow: Error...) -> MethodStub { - return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) - } - @MainActor - public static func publisher(willProduce: (StubberThrows>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func set(userId: Parameter) -> Verify { return Verify(method: .m_set__userId_userId(`userId`))} - public static func getUserID() -> Verify { return Verify(method: .m_getUserID)} - @MainActor - public static func publisher() -> Verify { return Verify(method: .m_publisher)} - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>) -> Verify { return Verify(method: .m_addToDownloadQueue__tasks_tasks(`tasks`))} - public static func saveOfflineProgress(progress: Parameter) -> Verify { return Verify(method: .m_saveOfflineProgress__progress_progress(`progress`))} - public static func loadProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_loadProgress__for_blockID(`blockID`))} - public static func loadAllOfflineProgress() -> Verify { return Verify(method: .m_loadAllOfflineProgress)} - public static func deleteProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_deleteProgress__for_blockID(`blockID`))} - public static func deleteAllProgress() -> Verify { return Verify(method: .m_deleteAllProgress)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`))} - public static func updateTask(task: Parameter) -> Verify { return Verify(method: .m_updateTask__task_task(`task`))} - public static func downloadDataTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadDataTask__for_blockId(`blockId`))} - public static func getDownloadDataTasks() -> Verify { return Verify(method: .m_getDownloadDataTasks)} - public static func getDownloadDataTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`))} - public static func deleteDownloadDataTasks(ids: Parameter<[String]>) -> Verify { return Verify(method: .m_deleteDownloadDataTasks__ids_ids(`ids`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func set(userId: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_set__userId_userId(`userId`), performs: perform) - } - public static func getUserID(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getUserID, performs: perform) - } - @MainActor - public static func publisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_publisher, performs: perform) - } - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>, perform: @escaping ([DownloadDataTask]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__tasks_tasks(`tasks`), performs: perform) - } - public static func saveOfflineProgress(progress: Parameter, perform: @escaping (OfflineProgress) -> Void) -> Perform { - return Perform(method: .m_saveOfflineProgress__progress_progress(`progress`), performs: perform) - } - public static func loadProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_loadProgress__for_blockID(`blockID`), performs: perform) - } - public static func loadAllOfflineProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_loadAllOfflineProgress, performs: perform) - } - public static func deleteProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_deleteProgress__for_blockID(`blockID`), performs: perform) - } - public static func deleteAllProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAllProgress, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter, perform: @escaping ([CourseBlock], DownloadQuality) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`), performs: perform) - } - public static func updateTask(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_updateTask__task_task(`task`), performs: perform) - } - public static func downloadDataTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadDataTask__for_blockId(`blockId`), performs: perform) - } - public static func getDownloadDataTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasks, performs: perform) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func deleteDownloadDataTasks(ids: Parameter<[String]>, perform: @escaping ([String]) -> Void) -> Perform { - return Perform(method: .m_deleteDownloadDataTasks__ids_ids(`ids`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreStorage - -open class CoreStorageMock: CoreStorage, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var accessToken: String? { - get { invocations.append(.p_accessToken_get); return __p_accessToken ?? optionalGivenGetterValue(.p_accessToken_get, "CoreStorageMock - stub value for accessToken was not defined") } - set { invocations.append(.p_accessToken_set(.value(newValue))); __p_accessToken = newValue } - } - private var __p_accessToken: (String)? - - public var refreshToken: String? { - get { invocations.append(.p_refreshToken_get); return __p_refreshToken ?? optionalGivenGetterValue(.p_refreshToken_get, "CoreStorageMock - stub value for refreshToken was not defined") } - set { invocations.append(.p_refreshToken_set(.value(newValue))); __p_refreshToken = newValue } - } - private var __p_refreshToken: (String)? - - public var pushToken: String? { - get { invocations.append(.p_pushToken_get); return __p_pushToken ?? optionalGivenGetterValue(.p_pushToken_get, "CoreStorageMock - stub value for pushToken was not defined") } - set { invocations.append(.p_pushToken_set(.value(newValue))); __p_pushToken = newValue } - } - private var __p_pushToken: (String)? - - public var appleSignFullName: String? { - get { invocations.append(.p_appleSignFullName_get); return __p_appleSignFullName ?? optionalGivenGetterValue(.p_appleSignFullName_get, "CoreStorageMock - stub value for appleSignFullName was not defined") } - set { invocations.append(.p_appleSignFullName_set(.value(newValue))); __p_appleSignFullName = newValue } - } - private var __p_appleSignFullName: (String)? - - public var appleSignEmail: String? { - get { invocations.append(.p_appleSignEmail_get); return __p_appleSignEmail ?? optionalGivenGetterValue(.p_appleSignEmail_get, "CoreStorageMock - stub value for appleSignEmail was not defined") } - set { invocations.append(.p_appleSignEmail_set(.value(newValue))); __p_appleSignEmail = newValue } - } - private var __p_appleSignEmail: (String)? - - public var cookiesDate: Date? { - get { invocations.append(.p_cookiesDate_get); return __p_cookiesDate ?? optionalGivenGetterValue(.p_cookiesDate_get, "CoreStorageMock - stub value for cookiesDate was not defined") } - set { invocations.append(.p_cookiesDate_set(.value(newValue))); __p_cookiesDate = newValue } - } - private var __p_cookiesDate: (Date)? - - public var reviewLastShownVersion: String? { - get { invocations.append(.p_reviewLastShownVersion_get); return __p_reviewLastShownVersion ?? optionalGivenGetterValue(.p_reviewLastShownVersion_get, "CoreStorageMock - stub value for reviewLastShownVersion was not defined") } - set { invocations.append(.p_reviewLastShownVersion_set(.value(newValue))); __p_reviewLastShownVersion = newValue } - } - private var __p_reviewLastShownVersion: (String)? - - public var lastReviewDate: Date? { - get { invocations.append(.p_lastReviewDate_get); return __p_lastReviewDate ?? optionalGivenGetterValue(.p_lastReviewDate_get, "CoreStorageMock - stub value for lastReviewDate was not defined") } - set { invocations.append(.p_lastReviewDate_set(.value(newValue))); __p_lastReviewDate = newValue } - } - private var __p_lastReviewDate: (Date)? - - public var user: DataLayer.User? { - get { invocations.append(.p_user_get); return __p_user ?? optionalGivenGetterValue(.p_user_get, "CoreStorageMock - stub value for user was not defined") } - set { invocations.append(.p_user_set(.value(newValue))); __p_user = newValue } - } - private var __p_user: (DataLayer.User)? - - public var userSettings: UserSettings? { - get { invocations.append(.p_userSettings_get); return __p_userSettings ?? optionalGivenGetterValue(.p_userSettings_get, "CoreStorageMock - stub value for userSettings was not defined") } - set { invocations.append(.p_userSettings_set(.value(newValue))); __p_userSettings = newValue } - } - private var __p_userSettings: (UserSettings)? - - public var resetAppSupportDirectoryUserData: Bool? { - get { invocations.append(.p_resetAppSupportDirectoryUserData_get); return __p_resetAppSupportDirectoryUserData ?? optionalGivenGetterValue(.p_resetAppSupportDirectoryUserData_get, "CoreStorageMock - stub value for resetAppSupportDirectoryUserData was not defined") } - set { invocations.append(.p_resetAppSupportDirectoryUserData_set(.value(newValue))); __p_resetAppSupportDirectoryUserData = newValue } - } - private var __p_resetAppSupportDirectoryUserData: (Bool)? - - public var useRelativeDates: Bool { - get { invocations.append(.p_useRelativeDates_get); return __p_useRelativeDates ?? givenGetterValue(.p_useRelativeDates_get, "CoreStorageMock - stub value for useRelativeDates was not defined") } - set { invocations.append(.p_useRelativeDates_set(.value(newValue))); __p_useRelativeDates = newValue } - } - private var __p_useRelativeDates: (Bool)? - - public var lastUsedSocialAuth: String? { - get { invocations.append(.p_lastUsedSocialAuth_get); return __p_lastUsedSocialAuth ?? optionalGivenGetterValue(.p_lastUsedSocialAuth_get, "CoreStorageMock - stub value for lastUsedSocialAuth was not defined") } - set { invocations.append(.p_lastUsedSocialAuth_set(.value(newValue))); __p_lastUsedSocialAuth = newValue } - } - private var __p_lastUsedSocialAuth: (String)? - - public var latestAvailableAppVersion: String? { - get { invocations.append(.p_latestAvailableAppVersion_get); return __p_latestAvailableAppVersion ?? optionalGivenGetterValue(.p_latestAvailableAppVersion_get, "CoreStorageMock - stub value for latestAvailableAppVersion was not defined") } - set { invocations.append(.p_latestAvailableAppVersion_set(.value(newValue))); __p_latestAvailableAppVersion = newValue } - } - private var __p_latestAvailableAppVersion: (String)? - - public var updateAppRequired: Bool { - get { invocations.append(.p_updateAppRequired_get); return __p_updateAppRequired ?? givenGetterValue(.p_updateAppRequired_get, "CoreStorageMock - stub value for updateAppRequired was not defined") } - set { invocations.append(.p_updateAppRequired_set(.value(newValue))); __p_updateAppRequired = newValue } - } - private var __p_updateAppRequired: (Bool)? - - - - - - open func clear() { - addInvocation(.m_clear) - let perform = methodPerformValue(.m_clear) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_clear - case p_accessToken_get - case p_accessToken_set(Parameter) - case p_refreshToken_get - case p_refreshToken_set(Parameter) - case p_pushToken_get - case p_pushToken_set(Parameter) - case p_appleSignFullName_get - case p_appleSignFullName_set(Parameter) - case p_appleSignEmail_get - case p_appleSignEmail_set(Parameter) - case p_cookiesDate_get - case p_cookiesDate_set(Parameter) - case p_reviewLastShownVersion_get - case p_reviewLastShownVersion_set(Parameter) - case p_lastReviewDate_get - case p_lastReviewDate_set(Parameter) - case p_user_get - case p_user_set(Parameter) - case p_userSettings_get - case p_userSettings_set(Parameter) - case p_resetAppSupportDirectoryUserData_get - case p_resetAppSupportDirectoryUserData_set(Parameter) - case p_useRelativeDates_get - case p_useRelativeDates_set(Parameter) - case p_lastUsedSocialAuth_get - case p_lastUsedSocialAuth_set(Parameter) - case p_latestAvailableAppVersion_get - case p_latestAvailableAppVersion_set(Parameter) - case p_updateAppRequired_get - case p_updateAppRequired_set(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_clear, .m_clear): return .match - case (.p_accessToken_get,.p_accessToken_get): return Matcher.ComparisonResult.match - case (.p_accessToken_set(let left),.p_accessToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_refreshToken_get,.p_refreshToken_get): return Matcher.ComparisonResult.match - case (.p_refreshToken_set(let left),.p_refreshToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_pushToken_get,.p_pushToken_get): return Matcher.ComparisonResult.match - case (.p_pushToken_set(let left),.p_pushToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignFullName_get,.p_appleSignFullName_get): return Matcher.ComparisonResult.match - case (.p_appleSignFullName_set(let left),.p_appleSignFullName_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignEmail_get,.p_appleSignEmail_get): return Matcher.ComparisonResult.match - case (.p_appleSignEmail_set(let left),.p_appleSignEmail_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_cookiesDate_get,.p_cookiesDate_get): return Matcher.ComparisonResult.match - case (.p_cookiesDate_set(let left),.p_cookiesDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_reviewLastShownVersion_get,.p_reviewLastShownVersion_get): return Matcher.ComparisonResult.match - case (.p_reviewLastShownVersion_set(let left),.p_reviewLastShownVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastReviewDate_get,.p_lastReviewDate_get): return Matcher.ComparisonResult.match - case (.p_lastReviewDate_set(let left),.p_lastReviewDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_user_get,.p_user_get): return Matcher.ComparisonResult.match - case (.p_user_set(let left),.p_user_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_userSettings_get,.p_userSettings_get): return Matcher.ComparisonResult.match - case (.p_userSettings_set(let left),.p_userSettings_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_resetAppSupportDirectoryUserData_get,.p_resetAppSupportDirectoryUserData_get): return Matcher.ComparisonResult.match - case (.p_resetAppSupportDirectoryUserData_set(let left),.p_resetAppSupportDirectoryUserData_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_useRelativeDates_get,.p_useRelativeDates_get): return Matcher.ComparisonResult.match - case (.p_useRelativeDates_set(let left),.p_useRelativeDates_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastUsedSocialAuth_get,.p_lastUsedSocialAuth_get): return Matcher.ComparisonResult.match - case (.p_lastUsedSocialAuth_set(let left),.p_lastUsedSocialAuth_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_latestAvailableAppVersion_get,.p_latestAvailableAppVersion_get): return Matcher.ComparisonResult.match - case (.p_latestAvailableAppVersion_set(let left),.p_latestAvailableAppVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_updateAppRequired_get,.p_updateAppRequired_get): return Matcher.ComparisonResult.match - case (.p_updateAppRequired_set(let left),.p_updateAppRequired_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_clear: return 0 - case .p_accessToken_get: return 0 - case .p_accessToken_set(let newValue): return newValue.intValue - case .p_refreshToken_get: return 0 - case .p_refreshToken_set(let newValue): return newValue.intValue - case .p_pushToken_get: return 0 - case .p_pushToken_set(let newValue): return newValue.intValue - case .p_appleSignFullName_get: return 0 - case .p_appleSignFullName_set(let newValue): return newValue.intValue - case .p_appleSignEmail_get: return 0 - case .p_appleSignEmail_set(let newValue): return newValue.intValue - case .p_cookiesDate_get: return 0 - case .p_cookiesDate_set(let newValue): return newValue.intValue - case .p_reviewLastShownVersion_get: return 0 - case .p_reviewLastShownVersion_set(let newValue): return newValue.intValue - case .p_lastReviewDate_get: return 0 - case .p_lastReviewDate_set(let newValue): return newValue.intValue - case .p_user_get: return 0 - case .p_user_set(let newValue): return newValue.intValue - case .p_userSettings_get: return 0 - case .p_userSettings_set(let newValue): return newValue.intValue - case .p_resetAppSupportDirectoryUserData_get: return 0 - case .p_resetAppSupportDirectoryUserData_set(let newValue): return newValue.intValue - case .p_useRelativeDates_get: return 0 - case .p_useRelativeDates_set(let newValue): return newValue.intValue - case .p_lastUsedSocialAuth_get: return 0 - case .p_lastUsedSocialAuth_set(let newValue): return newValue.intValue - case .p_latestAvailableAppVersion_get: return 0 - case .p_latestAvailableAppVersion_set(let newValue): return newValue.intValue - case .p_updateAppRequired_get: return 0 - case .p_updateAppRequired_set(let newValue): return newValue.intValue - } - } - func assertionName() -> String { - switch self { - case .m_clear: return ".clear()" - case .p_accessToken_get: return "[get] .accessToken" - case .p_accessToken_set: return "[set] .accessToken" - case .p_refreshToken_get: return "[get] .refreshToken" - case .p_refreshToken_set: return "[set] .refreshToken" - case .p_pushToken_get: return "[get] .pushToken" - case .p_pushToken_set: return "[set] .pushToken" - case .p_appleSignFullName_get: return "[get] .appleSignFullName" - case .p_appleSignFullName_set: return "[set] .appleSignFullName" - case .p_appleSignEmail_get: return "[get] .appleSignEmail" - case .p_appleSignEmail_set: return "[set] .appleSignEmail" - case .p_cookiesDate_get: return "[get] .cookiesDate" - case .p_cookiesDate_set: return "[set] .cookiesDate" - case .p_reviewLastShownVersion_get: return "[get] .reviewLastShownVersion" - case .p_reviewLastShownVersion_set: return "[set] .reviewLastShownVersion" - case .p_lastReviewDate_get: return "[get] .lastReviewDate" - case .p_lastReviewDate_set: return "[set] .lastReviewDate" - case .p_user_get: return "[get] .user" - case .p_user_set: return "[set] .user" - case .p_userSettings_get: return "[get] .userSettings" - case .p_userSettings_set: return "[set] .userSettings" - case .p_resetAppSupportDirectoryUserData_get: return "[get] .resetAppSupportDirectoryUserData" - case .p_resetAppSupportDirectoryUserData_set: return "[set] .resetAppSupportDirectoryUserData" - case .p_useRelativeDates_get: return "[get] .useRelativeDates" - case .p_useRelativeDates_set: return "[set] .useRelativeDates" - case .p_lastUsedSocialAuth_get: return "[get] .lastUsedSocialAuth" - case .p_lastUsedSocialAuth_set: return "[set] .lastUsedSocialAuth" - case .p_latestAvailableAppVersion_get: return "[get] .latestAvailableAppVersion" - case .p_latestAvailableAppVersion_set: return "[set] .latestAvailableAppVersion" - case .p_updateAppRequired_get: return "[get] .updateAppRequired" - case .p_updateAppRequired_set: return "[set] .updateAppRequired" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func accessToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_accessToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func refreshToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_refreshToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func pushToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_pushToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignFullName(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignFullName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignEmail(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func cookiesDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_cookiesDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func reviewLastShownVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_reviewLastShownVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastReviewDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_lastReviewDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func user(getter defaultValue: DataLayer.User?...) -> PropertyStub { - return Given(method: .p_user_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func userSettings(getter defaultValue: UserSettings?...) -> PropertyStub { - return Given(method: .p_userSettings_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func resetAppSupportDirectoryUserData(getter defaultValue: Bool?...) -> PropertyStub { - return Given(method: .p_resetAppSupportDirectoryUserData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func useRelativeDates(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_useRelativeDates_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastUsedSocialAuth(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_lastUsedSocialAuth_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func latestAvailableAppVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_latestAvailableAppVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func updateAppRequired(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_updateAppRequired_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func clear() -> Verify { return Verify(method: .m_clear)} - public static var accessToken: Verify { return Verify(method: .p_accessToken_get) } - public static func accessToken(set newValue: Parameter) -> Verify { return Verify(method: .p_accessToken_set(newValue)) } - public static var refreshToken: Verify { return Verify(method: .p_refreshToken_get) } - public static func refreshToken(set newValue: Parameter) -> Verify { return Verify(method: .p_refreshToken_set(newValue)) } - public static var pushToken: Verify { return Verify(method: .p_pushToken_get) } - public static func pushToken(set newValue: Parameter) -> Verify { return Verify(method: .p_pushToken_set(newValue)) } - public static var appleSignFullName: Verify { return Verify(method: .p_appleSignFullName_get) } - public static func appleSignFullName(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignFullName_set(newValue)) } - public static var appleSignEmail: Verify { return Verify(method: .p_appleSignEmail_get) } - public static func appleSignEmail(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignEmail_set(newValue)) } - public static var cookiesDate: Verify { return Verify(method: .p_cookiesDate_get) } - public static func cookiesDate(set newValue: Parameter) -> Verify { return Verify(method: .p_cookiesDate_set(newValue)) } - public static var reviewLastShownVersion: Verify { return Verify(method: .p_reviewLastShownVersion_get) } - public static func reviewLastShownVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_reviewLastShownVersion_set(newValue)) } - public static var lastReviewDate: Verify { return Verify(method: .p_lastReviewDate_get) } - public static func lastReviewDate(set newValue: Parameter) -> Verify { return Verify(method: .p_lastReviewDate_set(newValue)) } - public static var user: Verify { return Verify(method: .p_user_get) } - public static func user(set newValue: Parameter) -> Verify { return Verify(method: .p_user_set(newValue)) } - public static var userSettings: Verify { return Verify(method: .p_userSettings_get) } - public static func userSettings(set newValue: Parameter) -> Verify { return Verify(method: .p_userSettings_set(newValue)) } - public static var resetAppSupportDirectoryUserData: Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_get) } - public static func resetAppSupportDirectoryUserData(set newValue: Parameter) -> Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_set(newValue)) } - public static var useRelativeDates: Verify { return Verify(method: .p_useRelativeDates_get) } - public static func useRelativeDates(set newValue: Parameter) -> Verify { return Verify(method: .p_useRelativeDates_set(newValue)) } - public static var lastUsedSocialAuth: Verify { return Verify(method: .p_lastUsedSocialAuth_get) } - public static func lastUsedSocialAuth(set newValue: Parameter) -> Verify { return Verify(method: .p_lastUsedSocialAuth_set(newValue)) } - public static var latestAvailableAppVersion: Verify { return Verify(method: .p_latestAvailableAppVersion_get) } - public static func latestAvailableAppVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_latestAvailableAppVersion_set(newValue)) } - public static var updateAppRequired: Verify { return Verify(method: .p_updateAppRequired_get) } - public static func updateAppRequired(set newValue: Parameter) -> Verify { return Verify(method: .p_updateAppRequired_set(newValue)) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func clear(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_clear, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CourseStructureManagerProtocol - -open class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getLoadedCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func shiftDueDates(courseID: String) throws { - addInvocation(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - do { - _ = try methodReturnValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - - fileprivate enum MethodType { - case m_getCourseBlocks__courseID_courseID(Parameter) - case m_getLoadedCourseBlocks__courseID_courseID(Parameter) - case m_shiftDueDates__courseID_courseID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseBlocks__courseID_courseID(let lhsCourseid), .m_getCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getLoadedCourseBlocks__courseID_courseID(let lhsCourseid), .m_getLoadedCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_shiftDueDates__courseID_courseID(let lhsCourseid), .m_shiftDueDates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_getLoadedCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_shiftDueDates__courseID_courseID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getCourseBlocks__courseID_courseID: return ".getCourseBlocks(courseID:)" - case .m_getLoadedCourseBlocks__courseID_courseID: return ".getLoadedCourseBlocks(courseID:)" - case .m_shiftDueDates__courseID_courseID: return ".shiftDueDates(courseID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getLoadedCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func shiftDueDates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func shiftDueDates(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseBlocks__courseID_courseID(`courseID`))} - public static func getLoadedCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`))} - public static func shiftDueDates(courseID: Parameter) -> Verify { return Verify(method: .m_shiftDueDates__courseID_courseID(`courseID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func getLoadedCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func shiftDueDates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_shiftDueDates__courseID_courseID(`courseID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DatesInteractorProtocol - -open class DatesInteractorProtocolMock: DatesInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseDates(page: Int) throws -> ([CourseDate], String?) { - addInvocation(.m_getCourseDates__page_page(Parameter.value(`page`))) - let perform = methodPerformValue(.m_getCourseDates__page_page(Parameter.value(`page`))) as? (Int) -> Void - perform?(`page`) - var __value: ([CourseDate], String?) - do { - __value = try methodReturnValue(.m_getCourseDates__page_page(Parameter.value(`page`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseDates(page: Int). Use given") - Failure("Stub return value not specified for getCourseDates(page: Int). Use given") - } catch { - throw error - } - return __value - } - - open func getCourseDatesOffline(limit: Int?, offset: Int?) throws -> [CourseDate] { - addInvocation(.m_getCourseDatesOffline__limit_limitoffset_offset(Parameter.value(`limit`), Parameter.value(`offset`))) - let perform = methodPerformValue(.m_getCourseDatesOffline__limit_limitoffset_offset(Parameter.value(`limit`), Parameter.value(`offset`))) as? (Int?, Int?) -> Void - perform?(`limit`, `offset`) - var __value: [CourseDate] - do { - __value = try methodReturnValue(.m_getCourseDatesOffline__limit_limitoffset_offset(Parameter.value(`limit`), Parameter.value(`offset`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseDatesOffline(limit: Int?, offset: Int?). Use given") - Failure("Stub return value not specified for getCourseDatesOffline(limit: Int?, offset: Int?). Use given") - } catch { - throw error - } - return __value - } - - open func resetAllRelativeCourseDeadlines() throws { - addInvocation(.m_resetAllRelativeCourseDeadlines) - let perform = methodPerformValue(.m_resetAllRelativeCourseDeadlines) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_resetAllRelativeCourseDeadlines).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - - fileprivate enum MethodType { - case m_getCourseDates__page_page(Parameter) - case m_getCourseDatesOffline__limit_limitoffset_offset(Parameter, Parameter) - case m_resetAllRelativeCourseDeadlines - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseDates__page_page(let lhsPage), .m_getCourseDates__page_page(let rhsPage)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPage, rhs: rhsPage, with: matcher), lhsPage, rhsPage, "page")) - return Matcher.ComparisonResult(results) - - case (.m_getCourseDatesOffline__limit_limitoffset_offset(let lhsLimit, let lhsOffset), .m_getCourseDatesOffline__limit_limitoffset_offset(let rhsLimit, let rhsOffset)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsLimit, rhs: rhsLimit, with: matcher), lhsLimit, rhsLimit, "limit")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOffset, rhs: rhsOffset, with: matcher), lhsOffset, rhsOffset, "offset")) - return Matcher.ComparisonResult(results) - - case (.m_resetAllRelativeCourseDeadlines, .m_resetAllRelativeCourseDeadlines): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseDates__page_page(p0): return p0.intValue - case let .m_getCourseDatesOffline__limit_limitoffset_offset(p0, p1): return p0.intValue + p1.intValue - case .m_resetAllRelativeCourseDeadlines: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_getCourseDates__page_page: return ".getCourseDates(page:)" - case .m_getCourseDatesOffline__limit_limitoffset_offset: return ".getCourseDatesOffline(limit:offset:)" - case .m_resetAllRelativeCourseDeadlines: return ".resetAllRelativeCourseDeadlines()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseDates(page: Parameter, willReturn: ([CourseDate], String?)...) -> MethodStub { - return Given(method: .m_getCourseDates__page_page(`page`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseDatesOffline(limit: Parameter, offset: Parameter, willReturn: [CourseDate]...) -> MethodStub { - return Given(method: .m_getCourseDatesOffline__limit_limitoffset_offset(`limit`, `offset`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseDates(page: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseDates__page_page(`page`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseDates(page: Parameter, willProduce: (StubberThrows<([CourseDate], String?)>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseDates__page_page(`page`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (([CourseDate], String?)).self) - willProduce(stubber) - return given - } - public static func getCourseDatesOffline(limit: Parameter, offset: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseDatesOffline__limit_limitoffset_offset(`limit`, `offset`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseDatesOffline(limit: Parameter, offset: Parameter, willProduce: (StubberThrows<[CourseDate]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseDatesOffline__limit_limitoffset_offset(`limit`, `offset`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([CourseDate]).self) - willProduce(stubber) - return given - } - public static func resetAllRelativeCourseDeadlines(willThrow: Error...) -> MethodStub { - return Given(method: .m_resetAllRelativeCourseDeadlines, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resetAllRelativeCourseDeadlines(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resetAllRelativeCourseDeadlines, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseDates(page: Parameter) -> Verify { return Verify(method: .m_getCourseDates__page_page(`page`))} - public static func getCourseDatesOffline(limit: Parameter, offset: Parameter) -> Verify { return Verify(method: .m_getCourseDatesOffline__limit_limitoffset_offset(`limit`, `offset`))} - public static func resetAllRelativeCourseDeadlines() -> Verify { return Verify(method: .m_resetAllRelativeCourseDeadlines)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseDates(page: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_getCourseDates__page_page(`page`), performs: perform) - } - public static func getCourseDatesOffline(limit: Parameter, offset: Parameter, perform: @escaping (Int?, Int?) -> Void) -> Perform { - return Perform(method: .m_getCourseDatesOffline__limit_limitoffset_offset(`limit`, `offset`), performs: perform) - } - public static func resetAllRelativeCourseDeadlines(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_resetAllRelativeCourseDeadlines, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DatesPersistenceProtocol - -open class DatesPersistenceProtocolMock: DatesPersistenceProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func loadCourseDates(limit: Int?, offset: Int?) throws -> [CourseDate] { - addInvocation(.m_loadCourseDates__limit_limitoffset_offset(Parameter.value(`limit`), Parameter.value(`offset`))) - let perform = methodPerformValue(.m_loadCourseDates__limit_limitoffset_offset(Parameter.value(`limit`), Parameter.value(`offset`))) as? (Int?, Int?) -> Void - perform?(`limit`, `offset`) - var __value: [CourseDate] - do { - __value = try methodReturnValue(.m_loadCourseDates__limit_limitoffset_offset(Parameter.value(`limit`), Parameter.value(`offset`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for loadCourseDates(limit: Int?, offset: Int?). Use given") - Failure("Stub return value not specified for loadCourseDates(limit: Int?, offset: Int?). Use given") - } catch { - throw error - } - return __value - } - - open func saveCourseDates(dates: [CourseDate], startIndex: Int) { - addInvocation(.m_saveCourseDates__dates_datesstartIndex_startIndex(Parameter<[CourseDate]>.value(`dates`), Parameter.value(`startIndex`))) - let perform = methodPerformValue(.m_saveCourseDates__dates_datesstartIndex_startIndex(Parameter<[CourseDate]>.value(`dates`), Parameter.value(`startIndex`))) as? ([CourseDate], Int) -> Void - perform?(`dates`, `startIndex`) - } - - open func clearAllCourseDates() { - addInvocation(.m_clearAllCourseDates) - let perform = methodPerformValue(.m_clearAllCourseDates) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_loadCourseDates__limit_limitoffset_offset(Parameter, Parameter) - case m_saveCourseDates__dates_datesstartIndex_startIndex(Parameter<[CourseDate]>, Parameter) - case m_clearAllCourseDates - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_loadCourseDates__limit_limitoffset_offset(let lhsLimit, let lhsOffset), .m_loadCourseDates__limit_limitoffset_offset(let rhsLimit, let rhsOffset)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsLimit, rhs: rhsLimit, with: matcher), lhsLimit, rhsLimit, "limit")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOffset, rhs: rhsOffset, with: matcher), lhsOffset, rhsOffset, "offset")) - return Matcher.ComparisonResult(results) - - case (.m_saveCourseDates__dates_datesstartIndex_startIndex(let lhsDates, let lhsStartindex), .m_saveCourseDates__dates_datesstartIndex_startIndex(let rhsDates, let rhsStartindex)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDates, rhs: rhsDates, with: matcher), lhsDates, rhsDates, "dates")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsStartindex, rhs: rhsStartindex, with: matcher), lhsStartindex, rhsStartindex, "startIndex")) - return Matcher.ComparisonResult(results) - - case (.m_clearAllCourseDates, .m_clearAllCourseDates): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_loadCourseDates__limit_limitoffset_offset(p0, p1): return p0.intValue + p1.intValue - case let .m_saveCourseDates__dates_datesstartIndex_startIndex(p0, p1): return p0.intValue + p1.intValue - case .m_clearAllCourseDates: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_loadCourseDates__limit_limitoffset_offset: return ".loadCourseDates(limit:offset:)" - case .m_saveCourseDates__dates_datesstartIndex_startIndex: return ".saveCourseDates(dates:startIndex:)" - case .m_clearAllCourseDates: return ".clearAllCourseDates()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func loadCourseDates(limit: Parameter, offset: Parameter, willReturn: [CourseDate]...) -> MethodStub { - return Given(method: .m_loadCourseDates__limit_limitoffset_offset(`limit`, `offset`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadCourseDates(limit: Parameter, offset: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_loadCourseDates__limit_limitoffset_offset(`limit`, `offset`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func loadCourseDates(limit: Parameter, offset: Parameter, willProduce: (StubberThrows<[CourseDate]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_loadCourseDates__limit_limitoffset_offset(`limit`, `offset`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([CourseDate]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func loadCourseDates(limit: Parameter, offset: Parameter) -> Verify { return Verify(method: .m_loadCourseDates__limit_limitoffset_offset(`limit`, `offset`))} - public static func saveCourseDates(dates: Parameter<[CourseDate]>, startIndex: Parameter) -> Verify { return Verify(method: .m_saveCourseDates__dates_datesstartIndex_startIndex(`dates`, `startIndex`))} - public static func clearAllCourseDates() -> Verify { return Verify(method: .m_clearAllCourseDates)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func loadCourseDates(limit: Parameter, offset: Parameter, perform: @escaping (Int?, Int?) -> Void) -> Perform { - return Perform(method: .m_loadCourseDates__limit_limitoffset_offset(`limit`, `offset`), performs: perform) - } - public static func saveCourseDates(dates: Parameter<[CourseDate]>, startIndex: Parameter, perform: @escaping ([CourseDate], Int) -> Void) -> Perform { - return Perform(method: .m_saveCourseDates__dates_datesstartIndex_startIndex(`dates`, `startIndex`), performs: perform) - } - public static func clearAllCourseDates(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_clearAllCourseDates, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DownloadManagerProtocol - -open class DownloadManagerProtocolMock: DownloadManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCurrentDownloadTask() -> DownloadDataTask? { - addInvocation(.m_getCurrentDownloadTask) - let perform = methodPerformValue(.m_getCurrentDownloadTask) as? () -> Void - perform?() - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_getCurrentDownloadTask).casted() - } catch { - // do nothing - } - return __value - } - - open func eventPublisher() -> AnyPublisher { - addInvocation(.m_eventPublisher) - let perform = methodPerformValue(.m_eventPublisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_eventPublisher).casted() - } catch { - onFatalFailure("Stub return value not specified for eventPublisher(). Use given") - Failure("Stub return value not specified for eventPublisher(). Use given") - } - return __value - } - - open func addToDownloadQueue(blocks: [CourseBlock]) throws { - addInvocation(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - do { - _ = try methodReturnValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getDownloadTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasks) - let perform = methodPerformValue(.m_getDownloadTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasks(). Use given") - Failure("Stub return value not specified for getDownloadTasks(). Use given") - } - return __value - } - - open func getDownloadTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func cancelDownloading(courseId: String, blocks: [CourseBlock]) throws { - addInvocation(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) as? (String, [CourseBlock]) -> Void - perform?(`courseId`, `blocks`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(task: DownloadDataTask) throws { - addInvocation(.m_cancelDownloading__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_cancelDownloading__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - do { - _ = try methodReturnValue(.m_cancelDownloading__task_task(Parameter.value(`task`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(courseId: String) throws { - addInvocation(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelAllDownloading() throws { - addInvocation(.m_cancelAllDownloading) - let perform = methodPerformValue(.m_cancelAllDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_cancelAllDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func deleteAll() { - addInvocation(.m_deleteAll) - let perform = methodPerformValue(.m_deleteAll) as? () -> Void - perform?() - } - - open func fileUrl(for blockId: String) -> URL? { - addInvocation(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: URL? = nil - do { - __value = try methodReturnValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func resumeDownloading() throws { - addInvocation(.m_resumeDownloading) - let perform = methodPerformValue(.m_resumeDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_resumeDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func isLargeVideosSize(blocks: [CourseBlock]) -> Bool { - addInvocation(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - Failure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - } - return __value - } - - open func removeAppSupportDirectoryUnusedContent() { - addInvocation(.m_removeAppSupportDirectoryUnusedContent) - let perform = methodPerformValue(.m_removeAppSupportDirectoryUnusedContent) as? () -> Void - perform?() - } - - open func delete(blocks: [CourseBlock], courseId: String) { - addInvocation(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) as? ([CourseBlock], String) -> Void - perform?(`blocks`, `courseId`) - } - - open func downloadTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getFreeDiskSpace() -> Int? { - addInvocation(.m_getFreeDiskSpace) - let perform = methodPerformValue(.m_getFreeDiskSpace) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getFreeDiskSpace).casted() - } catch { - // do nothing - } - return __value - } - - - fileprivate enum MethodType { - case m_getCurrentDownloadTask - case m_eventPublisher - case m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>) - case m_getDownloadTasks - case m_getDownloadTasksForCourse__courseId(Parameter) - case m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter, Parameter<[CourseBlock]>) - case m_cancelDownloading__task_task(Parameter) - case m_cancelDownloading__courseId_courseId(Parameter) - case m_cancelAllDownloading - case m_deleteAll - case m_fileUrl__for_blockId(Parameter) - case m_resumeDownloading - case m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>) - case m_removeAppSupportDirectoryUnusedContent - case m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>, Parameter) - case m_downloadTask__for_blockId(Parameter) - case m_getFreeDiskSpace - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCurrentDownloadTask, .m_getCurrentDownloadTask): return .match - - case (.m_eventPublisher, .m_eventPublisher): return .match - - case (.m_addToDownloadQueue__blocks_blocks(let lhsBlocks), .m_addToDownloadQueue__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadTasks, .m_getDownloadTasks): return .match - - case (.m_getDownloadTasksForCourse__courseId(let lhsCourseid), .m_getDownloadTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseIdblocks_blocks(let lhsCourseid, let lhsBlocks), .m_cancelDownloading__courseId_courseIdblocks_blocks(let rhsCourseid, let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__task_task(let lhsTask), .m_cancelDownloading__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseId(let lhsCourseid), .m_cancelDownloading__courseId_courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelAllDownloading, .m_cancelAllDownloading): return .match - - case (.m_deleteAll, .m_deleteAll): return .match - - case (.m_fileUrl__for_blockId(let lhsBlockid), .m_fileUrl__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_resumeDownloading, .m_resumeDownloading): return .match - - case (.m_isLargeVideosSize__blocks_blocks(let lhsBlocks), .m_isLargeVideosSize__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_removeAppSupportDirectoryUnusedContent, .m_removeAppSupportDirectoryUnusedContent): return .match - - case (.m_delete__blocks_blockscourseId_courseId(let lhsBlocks, let lhsCourseid), .m_delete__blocks_blockscourseId_courseId(let rhsBlocks, let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_downloadTask__for_blockId(let lhsBlockid), .m_downloadTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getFreeDiskSpace, .m_getFreeDiskSpace): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_getCurrentDownloadTask: return 0 - case .m_eventPublisher: return 0 - case let .m_addToDownloadQueue__blocks_blocks(p0): return p0.intValue - case .m_getDownloadTasks: return 0 - case let .m_getDownloadTasksForCourse__courseId(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseIdblocks_blocks(p0, p1): return p0.intValue + p1.intValue - case let .m_cancelDownloading__task_task(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseId(p0): return p0.intValue - case .m_cancelAllDownloading: return 0 - case .m_deleteAll: return 0 - case let .m_fileUrl__for_blockId(p0): return p0.intValue - case .m_resumeDownloading: return 0 - case let .m_isLargeVideosSize__blocks_blocks(p0): return p0.intValue - case .m_removeAppSupportDirectoryUnusedContent: return 0 - case let .m_delete__blocks_blockscourseId_courseId(p0, p1): return p0.intValue + p1.intValue - case let .m_downloadTask__for_blockId(p0): return p0.intValue - case .m_getFreeDiskSpace: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_getCurrentDownloadTask: return ".getCurrentDownloadTask()" - case .m_eventPublisher: return ".eventPublisher()" - case .m_addToDownloadQueue__blocks_blocks: return ".addToDownloadQueue(blocks:)" - case .m_getDownloadTasks: return ".getDownloadTasks()" - case .m_getDownloadTasksForCourse__courseId: return ".getDownloadTasksForCourse(_:)" - case .m_cancelDownloading__courseId_courseIdblocks_blocks: return ".cancelDownloading(courseId:blocks:)" - case .m_cancelDownloading__task_task: return ".cancelDownloading(task:)" - case .m_cancelDownloading__courseId_courseId: return ".cancelDownloading(courseId:)" - case .m_cancelAllDownloading: return ".cancelAllDownloading()" - case .m_deleteAll: return ".deleteAll()" - case .m_fileUrl__for_blockId: return ".fileUrl(for:)" - case .m_resumeDownloading: return ".resumeDownloading()" - case .m_isLargeVideosSize__blocks_blocks: return ".isLargeVideosSize(blocks:)" - case .m_removeAppSupportDirectoryUnusedContent: return ".removeAppSupportDirectoryUnusedContent()" - case .m_delete__blocks_blockscourseId_courseId: return ".delete(blocks:courseId:)" - case .m_downloadTask__for_blockId: return ".downloadTask(for:)" - case .m_getFreeDiskSpace: return ".getFreeDiskSpace()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCurrentDownloadTask(willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func eventPublisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func fileUrl(for blockId: Parameter, willReturn: URL?...) -> MethodStub { - return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getFreeDiskSpace(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCurrentDownloadTask(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func eventPublisher(willProduce: (Stubber>) -> Void) -> MethodStub { - let willReturn: [AnyPublisher] = [] - let given: Given = { return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - public static func getDownloadTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func fileUrl(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [URL?] = [] - let given: Given = { return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (URL?).self) - willProduce(stubber) - return given - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func downloadTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getFreeDiskSpace(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(task: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(task: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelAllDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelAllDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func resumeDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resumeDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCurrentDownloadTask() -> Verify { return Verify(method: .m_getCurrentDownloadTask)} - public static func eventPublisher() -> Verify { return Verify(method: .m_eventPublisher)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocks(`blocks`))} - public static func getDownloadTasks() -> Verify { return Verify(method: .m_getDownloadTasks)} - public static func getDownloadTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadTasksForCourse__courseId(`courseId`))} - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`))} - public static func cancelDownloading(task: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__task_task(`task`))} - public static func cancelDownloading(courseId: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseId(`courseId`))} - public static func cancelAllDownloading() -> Verify { return Verify(method: .m_cancelAllDownloading)} - public static func deleteAll() -> Verify { return Verify(method: .m_deleteAll)} - public static func fileUrl(for blockId: Parameter) -> Verify { return Verify(method: .m_fileUrl__for_blockId(`blockId`))} - public static func resumeDownloading() -> Verify { return Verify(method: .m_resumeDownloading)} - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_isLargeVideosSize__blocks_blocks(`blocks`))} - public static func removeAppSupportDirectoryUnusedContent() -> Verify { return Verify(method: .m_removeAppSupportDirectoryUnusedContent)} - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter) -> Verify { return Verify(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`))} - public static func downloadTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadTask__for_blockId(`blockId`))} - public static func getFreeDiskSpace() -> Verify { return Verify(method: .m_getFreeDiskSpace)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCurrentDownloadTask(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getCurrentDownloadTask, performs: perform) - } - public static func eventPublisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_eventPublisher, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), performs: perform) - } - public static func getDownloadTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadTasks, performs: perform) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, perform: @escaping (String, [CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), performs: perform) - } - public static func cancelDownloading(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__task_task(`task`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseId(`courseId`), performs: perform) - } - public static func cancelAllDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_cancelAllDownloading, performs: perform) - } - public static func deleteAll(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAll, performs: perform) - } - public static func fileUrl(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_fileUrl__for_blockId(`blockId`), performs: perform) - } - public static func resumeDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_resumeDownloading, performs: perform) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), performs: perform) - } - public static func removeAppSupportDirectoryUnusedContent(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeAppSupportDirectoryUnusedContent, performs: perform) - } - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter, perform: @escaping ([CourseBlock], String) -> Void) -> Perform { - return Perform(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`), performs: perform) - } - public static func downloadTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadTask__for_blockId(`blockId`), performs: perform) - } - public static func getFreeDiskSpace(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getFreeDiskSpace, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - OfflineSyncInteractorProtocol - -open class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func submitOfflineProgress(courseID: String, blockID: String, data: String) throws -> Bool { - addInvocation(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) - let perform = methodPerformValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) as? (String, String, String) -> Void - perform?(`courseID`, `blockID`, `data`) - var __value: Bool - do { - __value = try methodReturnValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - Failure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter, Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let lhsCourseid, let lhsBlockid, let lhsData), .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let rhsCourseid, let rhsBlockid, let rhsData)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsData, rhs: rhsData, with: matcher), lhsData, rhsData, "data")) - return Matcher.ComparisonResult(results) - } - } - - func intValue() -> Int { - switch self { - case let .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data: return ".submitOfflineProgress(courseID:blockID:data:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter) -> Verify { return Verify(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - diff --git a/AppDates/AppDatesTests/AppDatesTests.swift b/AppDates/AppDatesTests/AppDatesTests.swift index 4e8946e2a..6c6b9d178 100644 --- a/AppDates/AppDatesTests/AppDatesTests.swift +++ b/AppDates/AppDatesTests/AppDatesTests.swift @@ -6,14 +6,13 @@ // import XCTest -import SwiftyMocky @testable import AppDates @testable import Core import SwiftUI @MainActor final class DatesViewModelTests: XCTestCase { - + func testLoadDatesSuccess() async throws { // Arrange let interactor = DatesInteractorProtocolMock() @@ -21,7 +20,7 @@ final class DatesViewModelTests: XCTestCase { let analytics = AppDatesAnalyticsMock() let courseManager = CourseStructureManagerProtocolMock() let router = AppDatesRouterMock() - + let viewModel = DatesViewModel( interactor: interactor, connectivity: connectivity, @@ -29,7 +28,7 @@ final class DatesViewModelTests: XCTestCase { analytics: analytics, router: router ) - + let date = Date() let courseDate1 = CourseDate( date: date.addingTimeInterval(60 * 60 * 24), // tomorrow @@ -39,7 +38,7 @@ final class DatesViewModelTests: XCTestCase { blockId: "block-123", hasAccess: true ) - + let courseDate2 = CourseDate( date: date.addingTimeInterval(60 * 60 * 24 * 7), // next week title: "Test title 2", @@ -48,25 +47,25 @@ final class DatesViewModelTests: XCTestCase { blockId: "block-456", hasAccess: true ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getCourseDatesOffline(limit: .value(20), offset: .value(0), willReturn: [courseDate1, courseDate2])) - Given(interactor, .getCourseDates(page: .value(1), willReturn: ([courseDate1, courseDate2], nil))) - + + connectivity.isInternetAvaliable = true + interactor.getCourseDatesOfflineHandler = { _, _ in [courseDate1, courseDate2] } + interactor.getCourseDatesHandler = { _ in ([courseDate1, courseDate2], nil) } + // Act await viewModel.loadDates() - + // Assert - Verify(interactor, 1, .getCourseDatesOffline(limit: .value(20), offset: .value(0))) - Verify(interactor, 1, .getCourseDates(page: .value(1))) - + XCTAssertEqual(interactor.getCourseDatesOfflineCallCount, 1) + XCTAssertEqual(interactor.getCourseDatesCallCount, 1) + XCTAssertEqual(viewModel.coursesDates.count, 2) XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.noDates) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.showError) } - + func testLoadDatesOfflineSuccess() async throws { // Arrange let interactor = DatesInteractorProtocolMock() @@ -74,7 +73,7 @@ final class DatesViewModelTests: XCTestCase { let analytics = AppDatesAnalyticsMock() let courseManager = CourseStructureManagerProtocolMock() let router = AppDatesRouterMock() - + let viewModel = DatesViewModel( interactor: interactor, connectivity: connectivity, @@ -82,7 +81,7 @@ final class DatesViewModelTests: XCTestCase { analytics: analytics, router: router ) - + let date = Date() let courseDate1 = CourseDate( date: date.addingTimeInterval(-60 * 60 * 24), // yesterday (pastDue) @@ -92,7 +91,7 @@ final class DatesViewModelTests: XCTestCase { blockId: "block-123", hasAccess: true ) - + let courseDate2 = CourseDate( date: date.addingTimeInterval(60 * 60), // later today (not past due) title: "Test title 2", @@ -101,16 +100,16 @@ final class DatesViewModelTests: XCTestCase { blockId: "block-456", hasAccess: true ) - - Given(connectivity, .isInternetAvaliable(getter: false)) - Given(interactor, .getCourseDatesOffline(limit: .value(nil), offset: .value(nil), willReturn: [courseDate1, courseDate2])) - + + connectivity.isInternetAvaliable = false + interactor.getCourseDatesOfflineHandler = { _, _ in [courseDate1, courseDate2] } + // Act await viewModel.loadDates() - + // Assert - Verify(interactor, 1, .getCourseDatesOffline(limit: .value(nil), offset: .value(nil))) - + XCTAssertEqual(interactor.getCourseDatesOfflineCallCount, 1) + XCTAssertEqual(viewModel.coursesDates.count, 2) XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.noDates) @@ -118,7 +117,7 @@ final class DatesViewModelTests: XCTestCase { XCTAssertFalse(viewModel.showError) XCTAssertTrue(viewModel.showShiftDueDatesView) } - + func testLoadDatesNoCachedDataError() async throws { // Arrange let interactor = DatesInteractorProtocolMock() @@ -126,7 +125,7 @@ final class DatesViewModelTests: XCTestCase { let analytics = AppDatesAnalyticsMock() let courseManager = CourseStructureManagerProtocolMock() let router = AppDatesRouterMock() - + let viewModel = DatesViewModel( interactor: interactor, connectivity: connectivity, @@ -134,22 +133,22 @@ final class DatesViewModelTests: XCTestCase { analytics: analytics, router: router ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getCourseDatesOffline(limit: .any, offset: .any, willThrow: NoCachedDataError())) - + + connectivity.isInternetAvaliable = true + interactor.getCourseDatesOfflineHandler = { _, _ in throw NoCachedDataError() } + // Act await viewModel.loadDates() - + // Assert - Verify(interactor, 1, .getCourseDatesOffline(limit: .value(20), offset: .value(0))) - + XCTAssertEqual(interactor.getCourseDatesOfflineCallCount, 1) + XCTAssertTrue(viewModel.coursesDates.isEmpty) XCTAssertFalse(viewModel.isShowProgress) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertTrue(viewModel.showError) } - + func testLoadDatesUnknownError() async throws { // Arrange let interactor = DatesInteractorProtocolMock() @@ -157,7 +156,7 @@ final class DatesViewModelTests: XCTestCase { let analytics = AppDatesAnalyticsMock() let courseManager = CourseStructureManagerProtocolMock() let router = AppDatesRouterMock() - + let viewModel = DatesViewModel( interactor: interactor, connectivity: connectivity, @@ -165,22 +164,24 @@ final class DatesViewModelTests: XCTestCase { analytics: analytics, router: router ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getCourseDatesOffline(limit: .any, offset: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + + connectivity.isInternetAvaliable = true + interactor.getCourseDatesOfflineHandler = { _, _ in + throw NSError(domain: "error", code: -1, userInfo: nil) + } + // Act await viewModel.loadDates() - + // Assert - Verify(interactor, 1, .getCourseDatesOffline(limit: .value(20), offset: .value(0))) - + XCTAssertEqual(interactor.getCourseDatesOfflineCallCount, 1) + XCTAssertTrue(viewModel.coursesDates.isEmpty) XCTAssertFalse(viewModel.isShowProgress) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertTrue(viewModel.showError) } - + func testLoadNextPage() async throws { // Arrange let interactor = DatesInteractorProtocolMock() @@ -188,7 +189,7 @@ final class DatesViewModelTests: XCTestCase { let analytics = AppDatesAnalyticsMock() let courseManager = CourseStructureManagerProtocolMock() let router = AppDatesRouterMock() - + let viewModel = DatesViewModel( interactor: interactor, connectivity: connectivity, @@ -196,7 +197,7 @@ final class DatesViewModelTests: XCTestCase { analytics: analytics, router: router ) - + let date = Date() let dates = (0...22).map { i in CourseDate( @@ -208,24 +209,24 @@ final class DatesViewModelTests: XCTestCase { hasAccess: true ) } - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getCourseDatesOffline(limit: .value(20), offset: .value(0), willReturn: Array(dates.prefix(20)))) - Given(interactor, .getCourseDates(page: .any, willReturn: (dates, "next-page"))) - + + connectivity.isInternetAvaliable = true + interactor.getCourseDatesOfflineHandler = { _, _ in Array(dates.prefix(20)) } + interactor.getCourseDatesHandler = { _ in (dates, "next-page") } + // Act await viewModel.loadDates() await viewModel.loadNextPageIfNeeded(for: dates[17]) - + // Assert - Verify(interactor, 1, .getCourseDatesOffline(limit: .value(20), offset: .value(0))) - Verify(interactor, 1, .getCourseDates(page: .value(1))) - + XCTAssertEqual(interactor.getCourseDatesOfflineCallCount, 1) + XCTAssertEqual(interactor.getCourseDatesCallCount, 1) + XCTAssertFalse(viewModel.isLoadingNextPage) XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.delayedLoadSecondPage) } - + func testLoadNextPageDelayedLoad() async throws { // Arrange let interactor = DatesInteractorProtocolMock() @@ -233,7 +234,7 @@ final class DatesViewModelTests: XCTestCase { let analytics = AppDatesAnalyticsMock() let courseManager = CourseStructureManagerProtocolMock() let router = AppDatesRouterMock() - + let viewModel = DatesViewModel( interactor: interactor, connectivity: connectivity, @@ -241,7 +242,7 @@ final class DatesViewModelTests: XCTestCase { analytics: analytics, router: router ) - + let date = Date() let dates = (0...22).map { i in CourseDate( @@ -253,17 +254,17 @@ final class DatesViewModelTests: XCTestCase { hasAccess: true ) } - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getCourseDatesOffline(limit: .value(20), offset: .value(0), willReturn: Array(dates.prefix(20)))) - Given(interactor, .getCourseDates(page: .any, willReturn: (dates, "next-page"))) - + + connectivity.isInternetAvaliable = true + interactor.getCourseDatesOfflineHandler = { _, _ in Array(dates.prefix(20)) } + interactor.getCourseDatesHandler = { _ in (dates, "next-page") } + // Act await viewModel.loadDates() await viewModel.loadNextPageIfNeeded(for: dates[17]) XCTAssertFalse(viewModel.fetchInProgress) } - + func testShiftDueDates() async throws { // Arrange let interactor = DatesInteractorProtocolMock() @@ -271,7 +272,7 @@ final class DatesViewModelTests: XCTestCase { let analytics = AppDatesAnalyticsMock() let courseManager = CourseStructureManagerProtocolMock() let router = AppDatesRouterMock() - + let viewModel = DatesViewModel( interactor: interactor, connectivity: connectivity, @@ -279,7 +280,7 @@ final class DatesViewModelTests: XCTestCase { analytics: analytics, router: router ) - + // Setup past due date let date = Date() let pastDueDate = CourseDate( @@ -290,25 +291,25 @@ final class DatesViewModelTests: XCTestCase { blockId: "block-123", hasAccess: true ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .resetAllRelativeCourseDeadlines(willProduce: {_ in })) - Given(interactor, .getCourseDates(page: .value(1), willReturn: ([], nil))) - Given(interactor, .getCourseDatesOffline(limit: .value(20), offset: .value(0), willReturn: [])) - + + connectivity.isInternetAvaliable = true + interactor.resetAllRelativeCourseDeadlinesHandler = { } + interactor.getCourseDatesHandler = { _ in ([], nil) } + interactor.getCourseDatesOfflineHandler = { _, _ in [] } + // Setup coursesDates with a pastDue group viewModel.coursesDates = [DateGroup(type: .pastDue, dates: [pastDueDate])] - + // Act await viewModel.shiftDueDates() - + // Assert - Verify(interactor, 1, .resetAllRelativeCourseDeadlines()) - + XCTAssertEqual(interactor.resetAllRelativeCourseDeadlinesCallCount, 1) + XCTAssertFalse(viewModel.isShowProgressForDueDates) XCTAssertFalse(viewModel.showShiftDueDatesView) } - + func testShiftDueDatesWithError() async throws { // Arrange let interactor = DatesInteractorProtocolMock() @@ -316,7 +317,7 @@ final class DatesViewModelTests: XCTestCase { let analytics = AppDatesAnalyticsMock() let courseManager = CourseStructureManagerProtocolMock() let router = AppDatesRouterMock() - + let viewModel = DatesViewModel( interactor: interactor, connectivity: connectivity, @@ -324,7 +325,7 @@ final class DatesViewModelTests: XCTestCase { analytics: analytics, router: router ) - + // Setup past due date let date = Date() let pastDueDate = CourseDate( @@ -335,35 +336,37 @@ final class DatesViewModelTests: XCTestCase { blockId: "block-123", hasAccess: true ) - + // Setup coursesDates with a pastDue group viewModel.coursesDates = [DateGroup(type: .pastDue, dates: [pastDueDate])] - + // Test internet error - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .resetAllRelativeCourseDeadlines(willThrow: NoCachedDataError())) - + connectivity.isInternetAvaliable = true + interactor.resetAllRelativeCourseDeadlinesHandler = { throw NoCachedDataError() } + // Act await viewModel.shiftDueDates() - + // Assert - Verify(interactor, 1, .resetAllRelativeCourseDeadlines()) + XCTAssertEqual(interactor.resetAllRelativeCourseDeadlinesCallCount, 1) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertTrue(viewModel.showError) XCTAssertFalse(viewModel.isShowProgressForDueDates) - + // Reset state viewModel.errorMessage = nil viewModel.showError = false - + // Test unknown error - Given(interactor, .resetAllRelativeCourseDeadlines(willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + interactor.resetAllRelativeCourseDeadlinesHandler = { + throw NSError(domain: "error", code: -1, userInfo: nil) + } + // Act await viewModel.shiftDueDates() - + // Assert - Verify(interactor, 2, .resetAllRelativeCourseDeadlines()) + XCTAssertEqual(interactor.resetAllRelativeCourseDeadlinesCallCount, 2) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertTrue(viewModel.showError) XCTAssertFalse(viewModel.isShowProgressForDueDates) diff --git a/AppDates/AppDatesTests/Generated/AppDatesMocks.generated.swift b/AppDates/AppDatesTests/Generated/AppDatesMocks.generated.swift new file mode 100644 index 000000000..07e731e7a --- /dev/null +++ b/AppDates/AppDatesTests/Generated/AppDatesMocks.generated.swift @@ -0,0 +1,2457 @@ +/// +/// @Generated by Mockolo +/// + + + +import Alamofire +@testable import AppDates +import Combine +@testable import Core +import CoreData +import Foundation +import OEXFoundation +import SwiftUI +import ZipArchive + + +public final class ConfigProtocolMock: ConfigProtocol, @unchecked Sendable { + public init() { } + public init(baseURL: URL = URL(fileURLWithPath: ""), baseSSOURL: URL = URL(fileURLWithPath: ""), ssoFinishedURL: URL = URL(fileURLWithPath: ""), ssoButtonTitle: [String: Any] = [String: Any](), oAuthClientId: String = "", tokenType: TokenType, feedbackEmail: String = "", appStoreLink: String = "", faq: URL? = nil, platformName: String = "", agreement: AgreementConfig, firebase: FirebaseConfig, facebook: FacebookConfig, microsoft: MicrosoftConfig, google: GoogleConfig, appleSignIn: AppleSignInConfig, features: FeaturesConfig, theme: ThemeConfig, uiComponents: UIComponentsConfig, discovery: DiscoveryConfig, dashboard: DashboardConfig, braze: BrazeConfig, branch: BranchConfig, program: DiscoveryConfig, experimentalFeatures: ExperimentalFeaturesConfig, URIScheme: String = "") { + self.baseURL = baseURL + self.baseSSOURL = baseSSOURL + self.ssoFinishedURL = ssoFinishedURL + self.ssoButtonTitle = ssoButtonTitle + self.oAuthClientId = oAuthClientId + self._tokenType = tokenType + self.feedbackEmail = feedbackEmail + self.appStoreLink = appStoreLink + self.faq = faq + self.platformName = platformName + self._agreement = agreement + self._firebase = firebase + self._facebook = facebook + self._microsoft = microsoft + self._google = google + self._appleSignIn = appleSignIn + self._features = features + self._theme = theme + self._uiComponents = uiComponents + self._discovery = discovery + self._dashboard = dashboard + self._braze = braze + self._branch = branch + self._program = program + self._experimentalFeatures = experimentalFeatures + self.URIScheme = URIScheme + } + + + + public var baseURL: URL = URL(fileURLWithPath: "") + + + public var baseSSOURL: URL = URL(fileURLWithPath: "") + + + public var ssoFinishedURL: URL = URL(fileURLWithPath: "") + + + public var ssoButtonTitle: [String: Any] = [String: Any]() + + + public var oAuthClientId: String = "" + + + private var _tokenType: TokenType! + public var tokenType: TokenType { + get { return _tokenType } + set { _tokenType = newValue } + } + + + public var feedbackEmail: String = "" + + + public var appStoreLink: String = "" + + + public var faq: URL? = nil + + + public var platformName: String = "" + + + private var _agreement: AgreementConfig! + public var agreement: AgreementConfig { + get { return _agreement } + set { _agreement = newValue } + } + + + private var _firebase: FirebaseConfig! + public var firebase: FirebaseConfig { + get { return _firebase } + set { _firebase = newValue } + } + + + private var _facebook: FacebookConfig! + public var facebook: FacebookConfig { + get { return _facebook } + set { _facebook = newValue } + } + + + private var _microsoft: MicrosoftConfig! + public var microsoft: MicrosoftConfig { + get { return _microsoft } + set { _microsoft = newValue } + } + + + private var _google: GoogleConfig! + public var google: GoogleConfig { + get { return _google } + set { _google = newValue } + } + + + private var _appleSignIn: AppleSignInConfig! + public var appleSignIn: AppleSignInConfig { + get { return _appleSignIn } + set { _appleSignIn = newValue } + } + + + private var _features: FeaturesConfig! + public var features: FeaturesConfig { + get { return _features } + set { _features = newValue } + } + + + private var _theme: ThemeConfig! + public var theme: ThemeConfig { + get { return _theme } + set { _theme = newValue } + } + + + private var _uiComponents: UIComponentsConfig! + public var uiComponents: UIComponentsConfig { + get { return _uiComponents } + set { _uiComponents = newValue } + } + + + private var _discovery: DiscoveryConfig! + public var discovery: DiscoveryConfig { + get { return _discovery } + set { _discovery = newValue } + } + + + private var _dashboard: DashboardConfig! + public var dashboard: DashboardConfig { + get { return _dashboard } + set { _dashboard = newValue } + } + + + private var _braze: BrazeConfig! + public var braze: BrazeConfig { + get { return _braze } + set { _braze = newValue } + } + + + private var _branch: BranchConfig! + public var branch: BranchConfig { + get { return _branch } + set { _branch = newValue } + } + + + private var _program: DiscoveryConfig! + public var program: DiscoveryConfig { + get { return _program } + set { _program = newValue } + } + + + private var _experimentalFeatures: ExperimentalFeaturesConfig! + public var experimentalFeatures: ExperimentalFeaturesConfig { + get { return _experimentalFeatures } + set { _experimentalFeatures = newValue } + } + + + public var URIScheme: String = "" +} + +public final class CoreAnalyticsMock: CoreAnalytics { + public init() { } + + + public private(set) var trackEventCallCount = 0 + public var trackEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackEventCallCount += 1 + if let trackEventHandler = trackEventHandler { + trackEventHandler(event, parameters) + } + + } + + public private(set) var trackEventBiValueCallCount = 0 + public var trackEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackEventBiValueCallCount += 1 + if let trackEventBiValueHandler = trackEventBiValueHandler { + trackEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var trackScreenEventCallCount = 0 + public var trackScreenEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackScreenEventCallCount += 1 + if let trackScreenEventHandler = trackScreenEventHandler { + trackScreenEventHandler(event, parameters) + } + + } + + public private(set) var trackScreenEventBiValueCallCount = 0 + public var trackScreenEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackScreenEventBiValueCallCount += 1 + if let trackScreenEventBiValueHandler = trackScreenEventBiValueHandler { + trackScreenEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var appreviewCallCount = 0 + public var appreviewHandler: ((AnalyticsEvent, EventBIValue, String?, Int?) -> ())? + public func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { + appreviewCallCount += 1 + if let appreviewHandler = appreviewHandler { + appreviewHandler(event, biValue, action, rating) + } + + } + + public private(set) var videoQualityChangedCallCount = 0 + public var videoQualityChangedHandler: ((AnalyticsEvent, EventBIValue, String, String) -> ())? + public func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { + videoQualityChangedCallCount += 1 + if let videoQualityChangedHandler = videoQualityChangedHandler { + videoQualityChangedHandler(event, bivalue, value, oldValue) + } + + } +} + +public final class CoreStorageMock: CoreStorage, @unchecked Sendable { + public init() { } + public init(accessToken: String? = nil, refreshToken: String? = nil, pushToken: String? = nil, appleSignFullName: String? = nil, appleSignEmail: String? = nil, cookiesDate: Date? = nil, reviewLastShownVersion: String? = nil, lastReviewDate: Date? = nil, user: DataLayer.User? = nil, userSettings: UserSettings? = nil, resetAppSupportDirectoryUserData: Bool? = nil, useRelativeDates: Bool = false, lastUsedSocialAuth: String? = nil, latestAvailableAppVersion: String? = nil, updateAppRequired: Bool = false) { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.pushToken = pushToken + self.appleSignFullName = appleSignFullName + self.appleSignEmail = appleSignEmail + self.cookiesDate = cookiesDate + self.reviewLastShownVersion = reviewLastShownVersion + self.lastReviewDate = lastReviewDate + self.user = user + self.userSettings = userSettings + self.resetAppSupportDirectoryUserData = resetAppSupportDirectoryUserData + self.useRelativeDates = useRelativeDates + self.lastUsedSocialAuth = lastUsedSocialAuth + self.latestAvailableAppVersion = latestAvailableAppVersion + self.updateAppRequired = updateAppRequired + } + + + public private(set) var accessTokenSetCallCount = 0 + public var accessToken: String? = nil { didSet { accessTokenSetCallCount += 1 } } + + public private(set) var refreshTokenSetCallCount = 0 + public var refreshToken: String? = nil { didSet { refreshTokenSetCallCount += 1 } } + + public private(set) var pushTokenSetCallCount = 0 + public var pushToken: String? = nil { didSet { pushTokenSetCallCount += 1 } } + + public private(set) var appleSignFullNameSetCallCount = 0 + public var appleSignFullName: String? = nil { didSet { appleSignFullNameSetCallCount += 1 } } + + public private(set) var appleSignEmailSetCallCount = 0 + public var appleSignEmail: String? = nil { didSet { appleSignEmailSetCallCount += 1 } } + + public private(set) var cookiesDateSetCallCount = 0 + public var cookiesDate: Date? = nil { didSet { cookiesDateSetCallCount += 1 } } + + public private(set) var reviewLastShownVersionSetCallCount = 0 + public var reviewLastShownVersion: String? = nil { didSet { reviewLastShownVersionSetCallCount += 1 } } + + public private(set) var lastReviewDateSetCallCount = 0 + public var lastReviewDate: Date? = nil { didSet { lastReviewDateSetCallCount += 1 } } + + public private(set) var userSetCallCount = 0 + public var user: DataLayer.User? = nil { didSet { userSetCallCount += 1 } } + + public private(set) var userSettingsSetCallCount = 0 + public var userSettings: UserSettings? = nil { didSet { userSettingsSetCallCount += 1 } } + + public private(set) var resetAppSupportDirectoryUserDataSetCallCount = 0 + public var resetAppSupportDirectoryUserData: Bool? = nil { didSet { resetAppSupportDirectoryUserDataSetCallCount += 1 } } + + public private(set) var useRelativeDatesSetCallCount = 0 + public var useRelativeDates: Bool = false { didSet { useRelativeDatesSetCallCount += 1 } } + + public private(set) var lastUsedSocialAuthSetCallCount = 0 + public var lastUsedSocialAuth: String? = nil { didSet { lastUsedSocialAuthSetCallCount += 1 } } + + public private(set) var latestAvailableAppVersionSetCallCount = 0 + public var latestAvailableAppVersion: String? = nil { didSet { latestAvailableAppVersionSetCallCount += 1 } } + + public private(set) var updateAppRequiredSetCallCount = 0 + public var updateAppRequired: Bool = false { didSet { updateAppRequiredSetCallCount += 1 } } + + private let clearState = MockoloMutex(MockoloHandlerState ()>()) + public var clearCallCount: Int { + return clearState.withLock(\.callCount) + } + public var clearHandler: (@Sendable () -> ())? { + get { clearState.withLock(\.handler) } + set { clearState.withLock { $0.handler = newValue } } + } + public func clear() { + let clearHandler = clearState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearHandler = clearHandler { + clearHandler() + } + + } +} + +public final class AuthInteractorProtocolMock: AuthInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let loginState = MockoloMutex(MockoloHandlerState User>()) + public var loginCallCount: Int { + return loginState.withLock(\.callCount) + } + public var loginHandler: (@Sendable (String, String) async throws -> User)? { + get { loginState.withLock(\.handler) } + set { loginState.withLock { $0.handler = newValue } } + } + public func login(username: String, password: String) async throws -> User { + let loginHandler = loginState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginHandler = loginHandler { + return try await loginHandler(username, password) + } + fatalError("loginHandler returns can't have a default value thus its handler must be set") + } + + private let loginExternalTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginExternalTokenCallCount: Int { + return loginExternalTokenState.withLock(\.callCount) + } + public var loginExternalTokenHandler: (@Sendable (String, String) async throws -> User)? { + get { loginExternalTokenState.withLock(\.handler) } + set { loginExternalTokenState.withLock { $0.handler = newValue } } + } + public func login(externalToken: String, backend: String) async throws -> User { + let loginExternalTokenHandler = loginExternalTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginExternalTokenHandler = loginExternalTokenHandler { + return try await loginExternalTokenHandler(externalToken, backend) + } + fatalError("loginExternalTokenHandler returns can't have a default value thus its handler must be set") + } + + private let loginSsoTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginSsoTokenCallCount: Int { + return loginSsoTokenState.withLock(\.callCount) + } + public var loginSsoTokenHandler: (@Sendable (String) async throws -> User)? { + get { loginSsoTokenState.withLock(\.handler) } + set { loginSsoTokenState.withLock { $0.handler = newValue } } + } + public func login(ssoToken: String) async throws -> User { + let loginSsoTokenHandler = loginSsoTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginSsoTokenHandler = loginSsoTokenHandler { + return try await loginSsoTokenHandler(ssoToken) + } + fatalError("loginSsoTokenHandler returns can't have a default value thus its handler must be set") + } + + private let resetPasswordState = MockoloMutex(MockoloHandlerState ResetPassword>()) + public var resetPasswordCallCount: Int { + return resetPasswordState.withLock(\.callCount) + } + public var resetPasswordHandler: (@Sendable (String) async throws -> ResetPassword)? { + get { resetPasswordState.withLock(\.handler) } + set { resetPasswordState.withLock { $0.handler = newValue } } + } + public func resetPassword(email: String) async throws -> ResetPassword { + let resetPasswordHandler = resetPasswordState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resetPasswordHandler = resetPasswordHandler { + return try await resetPasswordHandler(email) + } + fatalError("resetPasswordHandler returns can't have a default value thus its handler must be set") + } + + private let getCookiesState = MockoloMutex(MockoloHandlerState ()>()) + public var getCookiesCallCount: Int { + return getCookiesState.withLock(\.callCount) + } + public var getCookiesHandler: (@Sendable (Bool) async throws -> ())? { + get { getCookiesState.withLock(\.handler) } + set { getCookiesState.withLock { $0.handler = newValue } } + } + public func getCookies(force: Bool) async throws { + let getCookiesHandler = getCookiesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCookiesHandler = getCookiesHandler { + try await getCookiesHandler(force) + } + + } + + private let getRegistrationFieldsState = MockoloMutex(MockoloHandlerState [PickerFields]>()) + public var getRegistrationFieldsCallCount: Int { + return getRegistrationFieldsState.withLock(\.callCount) + } + public var getRegistrationFieldsHandler: (@Sendable () async throws -> [PickerFields])? { + get { getRegistrationFieldsState.withLock(\.handler) } + set { getRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func getRegistrationFields() async throws -> [PickerFields] { + let getRegistrationFieldsHandler = getRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getRegistrationFieldsHandler = getRegistrationFieldsHandler { + return try await getRegistrationFieldsHandler() + } + return [PickerFields]() + } + + private let registerUserState = MockoloMutex(MockoloHandlerState User>()) + public var registerUserCallCount: Int { + return registerUserState.withLock(\.callCount) + } + public var registerUserHandler: (@Sendable ([String: String], Bool) async throws -> User)? { + get { registerUserState.withLock(\.handler) } + set { registerUserState.withLock { $0.handler = newValue } } + } + public func registerUser(fields: [String: String], isSocial: Bool) async throws -> User { + let registerUserHandler = registerUserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let registerUserHandler = registerUserHandler { + return try await registerUserHandler(fields, isSocial) + } + fatalError("registerUserHandler returns can't have a default value thus its handler must be set") + } + + private let validateRegistrationFieldsState = MockoloMutex(MockoloHandlerState [String: String]>()) + public var validateRegistrationFieldsCallCount: Int { + return validateRegistrationFieldsState.withLock(\.callCount) + } + public var validateRegistrationFieldsHandler: (@Sendable ([String: String]) async throws -> [String: String])? { + get { validateRegistrationFieldsState.withLock(\.handler) } + set { validateRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func validateRegistrationFields(fields: [String: String]) async throws -> [String: String] { + let validateRegistrationFieldsHandler = validateRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let validateRegistrationFieldsHandler = validateRegistrationFieldsHandler { + return try await validateRegistrationFieldsHandler(fields) + } + return [String: String]() + } +} + +public final class AppDatesAnalyticsMock: AppDatesAnalytics, @unchecked Sendable { + public init() { } + + + private let mainDatesScreenViewedState = MockoloMutex(MockoloHandlerState ()>()) + public var mainDatesScreenViewedCallCount: Int { + return mainDatesScreenViewedState.withLock(\.callCount) + } + public var mainDatesScreenViewedHandler: (@Sendable () -> ())? { + get { mainDatesScreenViewedState.withLock(\.handler) } + set { mainDatesScreenViewedState.withLock { $0.handler = newValue } } + } + public func mainDatesScreenViewed() { + let mainDatesScreenViewedHandler = mainDatesScreenViewedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let mainDatesScreenViewedHandler = mainDatesScreenViewedHandler { + mainDatesScreenViewedHandler() + } + + } + + private let datesCourseClickedState = MockoloMutex(MockoloHandlerState ()>()) + public var datesCourseClickedCallCount: Int { + return datesCourseClickedState.withLock(\.callCount) + } + public var datesCourseClickedHandler: (@Sendable (String, String) -> ())? { + get { datesCourseClickedState.withLock(\.handler) } + set { datesCourseClickedState.withLock { $0.handler = newValue } } + } + public func datesCourseClicked(courseId: String, courseName: String) { + let datesCourseClickedHandler = datesCourseClickedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let datesCourseClickedHandler = datesCourseClickedHandler { + datesCourseClickedHandler(courseId, courseName) + } + + } + + private let datesSettingsClickedState = MockoloMutex(MockoloHandlerState ()>()) + public var datesSettingsClickedCallCount: Int { + return datesSettingsClickedState.withLock(\.callCount) + } + public var datesSettingsClickedHandler: (@Sendable () -> ())? { + get { datesSettingsClickedState.withLock(\.handler) } + set { datesSettingsClickedState.withLock { $0.handler = newValue } } + } + public func datesSettingsClicked() { + let datesSettingsClickedHandler = datesSettingsClickedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let datesSettingsClickedHandler = datesSettingsClickedHandler { + datesSettingsClickedHandler() + } + + } + + private let datesRefreshPulledState = MockoloMutex(MockoloHandlerState ()>()) + public var datesRefreshPulledCallCount: Int { + return datesRefreshPulledState.withLock(\.callCount) + } + public var datesRefreshPulledHandler: (@Sendable () -> ())? { + get { datesRefreshPulledState.withLock(\.handler) } + set { datesRefreshPulledState.withLock { $0.handler = newValue } } + } + public func datesRefreshPulled() { + let datesRefreshPulledHandler = datesRefreshPulledState.withLock { state in + state.callCount += 1 + return state.handler + } + if let datesRefreshPulledHandler = datesRefreshPulledHandler { + datesRefreshPulledHandler() + } + + } +} + +public final class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let submitOfflineProgressState = MockoloMutex(MockoloHandlerState Bool>()) + public var submitOfflineProgressCallCount: Int { + return submitOfflineProgressState.withLock(\.callCount) + } + public var submitOfflineProgressHandler: (@Sendable (String, String, String) async throws -> Bool)? { + get { submitOfflineProgressState.withLock(\.handler) } + set { submitOfflineProgressState.withLock { $0.handler = newValue } } + } + public func submitOfflineProgress(courseID: String, blockID: String, data: String) async throws -> Bool { + let submitOfflineProgressHandler = submitOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let submitOfflineProgressHandler = submitOfflineProgressHandler { + return try await submitOfflineProgressHandler(courseID, blockID, data) + } + return false + } +} + +public final class WebviewCookiesUpdateProtocolMock: WebviewCookiesUpdateProtocol { + public init() { } + public init(authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock(), cookiesReady: Bool = false, updatingCookies: Bool = false, errorMessage: String? = nil) { + self.authInteractor = authInteractor + self.cookiesReady = cookiesReady + self.updatingCookies = updatingCookies + self.errorMessage = errorMessage + } + + + + public var authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock() + + public private(set) var cookiesReadySetCallCount = 0 + public var cookiesReady: Bool = false { didSet { cookiesReadySetCallCount += 1 } } + + public private(set) var updatingCookiesSetCallCount = 0 + public var updatingCookies: Bool = false { didSet { updatingCookiesSetCallCount += 1 } } + + public private(set) var errorMessageSetCallCount = 0 + public var errorMessage: String? = nil { didSet { errorMessageSetCallCount += 1 } } + + public private(set) var updateCookiesCallCount = 0 + public var updateCookiesHandler: ((Bool, Int) async -> ())? + public func updateCookies(force: Bool, retryCount: Int) async { + updateCookiesCallCount += 1 + if let updateCookiesHandler = updateCookiesHandler { + await updateCookiesHandler(force, retryCount) + } + + } +} + +public final class BaseRouterMock: BaseRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class CalendarManagerProtocolMock: CalendarManagerProtocol, @unchecked Sendable { + public init() { } + + + private let createCalendarIfNeededState = MockoloMutex(MockoloHandlerState ()>()) + public var createCalendarIfNeededCallCount: Int { + return createCalendarIfNeededState.withLock(\.callCount) + } + public var createCalendarIfNeededHandler: (@Sendable () -> ())? { + get { createCalendarIfNeededState.withLock(\.handler) } + set { createCalendarIfNeededState.withLock { $0.handler = newValue } } + } + public func createCalendarIfNeeded() { + let createCalendarIfNeededHandler = createCalendarIfNeededState.withLock { state in + state.callCount += 1 + return state.handler + } + if let createCalendarIfNeededHandler = createCalendarIfNeededHandler { + createCalendarIfNeededHandler() + } + + } + + private let filterCoursesBySelectedState = MockoloMutex(MockoloHandlerState [CourseForSync]>()) + public var filterCoursesBySelectedCallCount: Int { + return filterCoursesBySelectedState.withLock(\.callCount) + } + public var filterCoursesBySelectedHandler: (@Sendable ([CourseForSync]) async -> [CourseForSync])? { + get { filterCoursesBySelectedState.withLock(\.handler) } + set { filterCoursesBySelectedState.withLock { $0.handler = newValue } } + } + public func filterCoursesBySelected(fetchedCourses: [CourseForSync]) async -> [CourseForSync] { + let filterCoursesBySelectedHandler = filterCoursesBySelectedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let filterCoursesBySelectedHandler = filterCoursesBySelectedHandler { + return await filterCoursesBySelectedHandler(fetchedCourses) + } + return [CourseForSync]() + } + + private let removeOldCalendarState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOldCalendarCallCount: Int { + return removeOldCalendarState.withLock(\.callCount) + } + public var removeOldCalendarHandler: (@Sendable () -> ())? { + get { removeOldCalendarState.withLock(\.handler) } + set { removeOldCalendarState.withLock { $0.handler = newValue } } + } + public func removeOldCalendar() { + let removeOldCalendarHandler = removeOldCalendarState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOldCalendarHandler = removeOldCalendarHandler { + removeOldCalendarHandler() + } + + } + + private let removeOutdatedEventsState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOutdatedEventsCallCount: Int { + return removeOutdatedEventsState.withLock(\.callCount) + } + public var removeOutdatedEventsHandler: (@Sendable (String) async -> ())? { + get { removeOutdatedEventsState.withLock(\.handler) } + set { removeOutdatedEventsState.withLock { $0.handler = newValue } } + } + public func removeOutdatedEvents(courseID: String) async { + let removeOutdatedEventsHandler = removeOutdatedEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOutdatedEventsHandler = removeOutdatedEventsHandler { + await removeOutdatedEventsHandler(courseID) + } + + } + + private let syncCourseState = MockoloMutex(MockoloHandlerState ()>()) + public var syncCourseCallCount: Int { + return syncCourseState.withLock(\.callCount) + } + public var syncCourseHandler: (@Sendable (String, String, CourseDates) async -> ())? { + get { syncCourseState.withLock(\.handler) } + set { syncCourseState.withLock { $0.handler = newValue } } + } + public func syncCourse(courseID: String, courseName: String, dates: CourseDates) async { + let syncCourseHandler = syncCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let syncCourseHandler = syncCourseHandler { + await syncCourseHandler(courseID, courseName, dates) + } + + } + + private let requestAccessState = MockoloMutex(MockoloHandlerState Bool>()) + public var requestAccessCallCount: Int { + return requestAccessState.withLock(\.callCount) + } + public var requestAccessHandler: (@Sendable () async -> Bool)? { + get { requestAccessState.withLock(\.handler) } + set { requestAccessState.withLock { $0.handler = newValue } } + } + public func requestAccess() async -> Bool { + let requestAccessHandler = requestAccessState.withLock { state in + state.callCount += 1 + return state.handler + } + if let requestAccessHandler = requestAccessHandler { + return await requestAccessHandler() + } + return false + } + + private let courseStatusState = MockoloMutex(MockoloHandlerState SyncStatus>()) + public var courseStatusCallCount: Int { + return courseStatusState.withLock(\.callCount) + } + public var courseStatusHandler: (@Sendable (String) async -> SyncStatus)? { + get { courseStatusState.withLock(\.handler) } + set { courseStatusState.withLock { $0.handler = newValue } } + } + public func courseStatus(courseID: String) async -> SyncStatus { + let courseStatusHandler = courseStatusState.withLock { state in + state.callCount += 1 + return state.handler + } + if let courseStatusHandler = courseStatusHandler { + return await courseStatusHandler(courseID) + } + fatalError("courseStatusHandler returns can't have a default value thus its handler must be set") + } + + private let clearAllDataState = MockoloMutex(MockoloHandlerState ()>()) + public var clearAllDataCallCount: Int { + return clearAllDataState.withLock(\.callCount) + } + public var clearAllDataHandler: (@Sendable (Bool) async -> ())? { + get { clearAllDataState.withLock(\.handler) } + set { clearAllDataState.withLock { $0.handler = newValue } } + } + public func clearAllData(removeCalendar: Bool) async { + let clearAllDataHandler = clearAllDataState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearAllDataHandler = clearAllDataHandler { + await clearAllDataHandler(removeCalendar) + } + + } + + private let isDatesChangedState = MockoloMutex(MockoloHandlerState Bool>()) + public var isDatesChangedCallCount: Int { + return isDatesChangedState.withLock(\.callCount) + } + public var isDatesChangedHandler: (@Sendable (String, String) async -> Bool)? { + get { isDatesChangedState.withLock(\.handler) } + set { isDatesChangedState.withLock { $0.handler = newValue } } + } + public func isDatesChanged(courseID: String, checksum: String) async -> Bool { + let isDatesChangedHandler = isDatesChangedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isDatesChangedHandler = isDatesChangedHandler { + return await isDatesChangedHandler(courseID, checksum) + } + return false + } +} + +public final class AppDatesRouterMock: AppDatesRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let showSettingsState = MockoloMutex(MockoloHandlerState ()>()) + public var showSettingsCallCount: Int { + return showSettingsState.withLock(\.callCount) + } + public var showSettingsHandler: (@Sendable () -> ())? { + get { showSettingsState.withLock(\.handler) } + set { showSettingsState.withLock { $0.handler = newValue } } + } + public func showSettings() { + let showSettingsHandler = showSettingsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSettingsHandler = showSettingsHandler { + showSettingsHandler() + } + + } + + private let showUpdateRequiredViewState = MockoloMutex(MockoloHandlerState ()>()) + public var showUpdateRequiredViewCallCount: Int { + return showUpdateRequiredViewState.withLock(\.callCount) + } + public var showUpdateRequiredViewHandler: (@Sendable (Bool) -> ())? { + get { showUpdateRequiredViewState.withLock(\.handler) } + set { showUpdateRequiredViewState.withLock { $0.handler = newValue } } + } + public func showUpdateRequiredView(showAccountLink: Bool) { + let showUpdateRequiredViewHandler = showUpdateRequiredViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showUpdateRequiredViewHandler = showUpdateRequiredViewHandler { + showUpdateRequiredViewHandler(showAccountLink) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let showCourseScreensState = MockoloMutex(MockoloHandlerState ()>()) + public var showCourseScreensCallCount: Int { + return showCourseScreensState.withLock(\.callCount) + } + public var showCourseScreensHandler: (@Sendable (String, Bool?, Date?, Date?, Date?, Date?, String, String?, Bool, String?) -> ())? { + get { showCourseScreensState.withLock(\.handler) } + set { showCourseScreensState.withLock { $0.handler = newValue } } + } + public func showCourseScreens(courseID: String, hasAccess: Bool?, courseStart: Date?, courseEnd: Date?, enrollmentStart: Date?, enrollmentEnd: Date?, title: String, courseRawImage: String?, showDates: Bool, lastVisitedBlockID: String?) { + let showCourseScreensHandler = showCourseScreensState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showCourseScreensHandler = showCourseScreensHandler { + showCourseScreensHandler(courseID, hasAccess, courseStart, courseEnd, enrollmentStart, enrollmentEnd, title, courseRawImage, showDates, lastVisitedBlockID) + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class CorePersistenceProtocolMock: CorePersistenceProtocol, @unchecked Sendable { + public init() { } + + + private let setState = MockoloMutex(MockoloHandlerState ()>()) + public var setCallCount: Int { + return setState.withLock(\.callCount) + } + public var setHandler: (@Sendable (Int) -> ())? { + get { setState.withLock(\.handler) } + set { setState.withLock { $0.handler = newValue } } + } + public func set(userId: Int) { + let setHandler = setState.withLock { state in + state.callCount += 1 + return state.handler + } + if let setHandler = setHandler { + setHandler(userId) + } + + } + + private let getUserIDState = MockoloMutex(MockoloHandlerState Int?>()) + public var getUserIDCallCount: Int { + return getUserIDState.withLock(\.callCount) + } + public var getUserIDHandler: (@Sendable () -> Int?)? { + get { getUserIDState.withLock(\.handler) } + set { getUserIDState.withLock { $0.handler = newValue } } + } + public func getUserID() -> Int? { + let getUserIDHandler = getUserIDState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getUserIDHandler = getUserIDHandler { + return getUserIDHandler() + } + return nil + } + + private let publisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var publisherCallCount: Int { + return publisherState.withLock(\.callCount) + } + public var publisherHandler: (@Sendable () throws -> AnyPublisher)? { + get { publisherState.withLock(\.handler) } + set { publisherState.withLock { $0.handler = newValue } } + } + public func publisher() throws -> AnyPublisher { + let publisherHandler = publisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let publisherHandler = publisherHandler { + return try publisherHandler() + } + fatalError("publisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([DownloadDataTask]) -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(tasks: [DownloadDataTask]) { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + addToDownloadQueueHandler(tasks) + } + + } + + private let saveOfflineProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var saveOfflineProgressCallCount: Int { + return saveOfflineProgressState.withLock(\.callCount) + } + public var saveOfflineProgressHandler: (@Sendable (OfflineProgress) async -> ())? { + get { saveOfflineProgressState.withLock(\.handler) } + set { saveOfflineProgressState.withLock { $0.handler = newValue } } + } + public func saveOfflineProgress(progress: OfflineProgress) async { + let saveOfflineProgressHandler = saveOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveOfflineProgressHandler = saveOfflineProgressHandler { + await saveOfflineProgressHandler(progress) + } + + } + + private let loadProgressState = MockoloMutex(MockoloHandlerState OfflineProgress?>()) + public var loadProgressCallCount: Int { + return loadProgressState.withLock(\.callCount) + } + public var loadProgressHandler: (@Sendable (String) async -> OfflineProgress?)? { + get { loadProgressState.withLock(\.handler) } + set { loadProgressState.withLock { $0.handler = newValue } } + } + public func loadProgress(for blockID: String) async -> OfflineProgress? { + let loadProgressHandler = loadProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadProgressHandler = loadProgressHandler { + return await loadProgressHandler(blockID) + } + return nil + } + + private let loadAllOfflineProgressState = MockoloMutex(MockoloHandlerState [OfflineProgress]>()) + public var loadAllOfflineProgressCallCount: Int { + return loadAllOfflineProgressState.withLock(\.callCount) + } + public var loadAllOfflineProgressHandler: (@Sendable () async -> [OfflineProgress])? { + get { loadAllOfflineProgressState.withLock(\.handler) } + set { loadAllOfflineProgressState.withLock { $0.handler = newValue } } + } + public func loadAllOfflineProgress() async -> [OfflineProgress] { + let loadAllOfflineProgressHandler = loadAllOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadAllOfflineProgressHandler = loadAllOfflineProgressHandler { + return await loadAllOfflineProgressHandler() + } + return [OfflineProgress]() + } + + private let deleteProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteProgressCallCount: Int { + return deleteProgressState.withLock(\.callCount) + } + public var deleteProgressHandler: (@Sendable (String) async -> ())? { + get { deleteProgressState.withLock(\.handler) } + set { deleteProgressState.withLock { $0.handler = newValue } } + } + public func deleteProgress(for blockID: String) async { + let deleteProgressHandler = deleteProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteProgressHandler = deleteProgressHandler { + await deleteProgressHandler(blockID) + } + + } + + private let deleteAllProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllProgressCallCount: Int { + return deleteAllProgressState.withLock(\.callCount) + } + public var deleteAllProgressHandler: (@Sendable () async -> ())? { + get { deleteAllProgressState.withLock(\.handler) } + set { deleteAllProgressState.withLock { $0.handler = newValue } } + } + public func deleteAllProgress() async { + let deleteAllProgressHandler = deleteAllProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllProgressHandler = deleteAllProgressHandler { + await deleteAllProgressHandler() + } + + } + + private let addToDownloadQueueBlocksState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueBlocksCallCount: Int { + return addToDownloadQueueBlocksState.withLock(\.callCount) + } + public var addToDownloadQueueBlocksHandler: (@Sendable ([CourseBlock], DownloadQuality) -> ())? { + get { addToDownloadQueueBlocksState.withLock(\.handler) } + set { addToDownloadQueueBlocksState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { + let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksHandler { + addToDownloadQueueBlocksHandler(blocks, downloadQuality) + } + + } + + private let updateTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var updateTaskCallCount: Int { + return updateTaskState.withLock(\.callCount) + } + public var updateTaskHandler: (@Sendable (DownloadDataTask) -> ())? { + get { updateTaskState.withLock(\.handler) } + set { updateTaskState.withLock { $0.handler = newValue } } + } + public func updateTask(task: DownloadDataTask) { + let updateTaskHandler = updateTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateTaskHandler = updateTaskHandler { + updateTaskHandler(task) + } + + } + + private let downloadDataTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadDataTaskCallCount: Int { + return downloadDataTaskState.withLock(\.callCount) + } + public var downloadDataTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadDataTaskState.withLock(\.handler) } + set { downloadDataTaskState.withLock { $0.handler = newValue } } + } + public func downloadDataTask(for blockId: String) async -> DownloadDataTask? { + let downloadDataTaskHandler = downloadDataTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadDataTaskHandler = downloadDataTaskHandler { + return await downloadDataTaskHandler(blockId) + } + return nil + } + + private let getDownloadDataTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksCallCount: Int { + return getDownloadDataTasksState.withLock(\.callCount) + } + public var getDownloadDataTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadDataTasksState.withLock(\.handler) } + set { getDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasks() async -> [DownloadDataTask] { + let getDownloadDataTasksHandler = getDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksHandler = getDownloadDataTasksHandler { + return await getDownloadDataTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadDataTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksForCourseCallCount: Int { + return getDownloadDataTasksForCourseState.withLock(\.callCount) + } + public var getDownloadDataTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadDataTasksForCourseState.withLock(\.handler) } + set { getDownloadDataTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseHandler { + return await getDownloadDataTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let deleteDownloadDataTasksState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteDownloadDataTasksCallCount: Int { + return deleteDownloadDataTasksState.withLock(\.callCount) + } + public var deleteDownloadDataTasksHandler: (@Sendable ([String]) -> ())? { + get { deleteDownloadDataTasksState.withLock(\.handler) } + set { deleteDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func deleteDownloadDataTasks(ids: [String]) { + let deleteDownloadDataTasksHandler = deleteDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteDownloadDataTasksHandler = deleteDownloadDataTasksHandler { + deleteDownloadDataTasksHandler(ids) + } + + } +} + +public final class DatesInteractorProtocolMock: DatesInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseDatesState = MockoloMutex(MockoloHandlerState ([CourseDate], String?)>()) + public var getCourseDatesCallCount: Int { + return getCourseDatesState.withLock(\.callCount) + } + public var getCourseDatesHandler: (@Sendable (Int) async throws -> ([CourseDate], String?))? { + get { getCourseDatesState.withLock(\.handler) } + set { getCourseDatesState.withLock { $0.handler = newValue } } + } + public func getCourseDates(page: Int) async throws -> ([CourseDate], String?) { + let getCourseDatesHandler = getCourseDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDatesHandler = getCourseDatesHandler { + return try await getCourseDatesHandler(page) + } + return ([CourseDate](), nil) + } + + private let getCourseDatesOfflineState = MockoloMutex(MockoloHandlerState [CourseDate]>()) + public var getCourseDatesOfflineCallCount: Int { + return getCourseDatesOfflineState.withLock(\.callCount) + } + public var getCourseDatesOfflineHandler: (@Sendable (Int?, Int?) async throws -> [CourseDate])? { + get { getCourseDatesOfflineState.withLock(\.handler) } + set { getCourseDatesOfflineState.withLock { $0.handler = newValue } } + } + public func getCourseDatesOffline(limit: Int?, offset: Int?) async throws -> [CourseDate] { + let getCourseDatesOfflineHandler = getCourseDatesOfflineState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDatesOfflineHandler = getCourseDatesOfflineHandler { + return try await getCourseDatesOfflineHandler(limit, offset) + } + return [CourseDate]() + } + + private let resetAllRelativeCourseDeadlinesState = MockoloMutex(MockoloHandlerState ()>()) + public var resetAllRelativeCourseDeadlinesCallCount: Int { + return resetAllRelativeCourseDeadlinesState.withLock(\.callCount) + } + public var resetAllRelativeCourseDeadlinesHandler: (@Sendable () async throws -> ())? { + get { resetAllRelativeCourseDeadlinesState.withLock(\.handler) } + set { resetAllRelativeCourseDeadlinesState.withLock { $0.handler = newValue } } + } + public func resetAllRelativeCourseDeadlines() async throws { + let resetAllRelativeCourseDeadlinesHandler = resetAllRelativeCourseDeadlinesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resetAllRelativeCourseDeadlinesHandler = resetAllRelativeCourseDeadlinesHandler { + try await resetAllRelativeCourseDeadlinesHandler() + } + + } +} + +public final class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseBlocksCallCount: Int { + return getCourseBlocksState.withLock(\.callCount) + } + public var getCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getCourseBlocksState.withLock(\.handler) } + set { getCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseBlocks(courseID: String) async throws -> CourseStructure { + let getCourseBlocksHandler = getCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseBlocksHandler = getCourseBlocksHandler { + return try await getCourseBlocksHandler(courseID) + } + fatalError("getCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getLoadedCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getLoadedCourseBlocksCallCount: Int { + return getLoadedCourseBlocksState.withLock(\.callCount) + } + public var getLoadedCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getLoadedCourseBlocksState.withLock(\.handler) } + set { getLoadedCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure { + let getLoadedCourseBlocksHandler = getLoadedCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseBlocksHandler = getLoadedCourseBlocksHandler { + return try await getLoadedCourseBlocksHandler(courseID) + } + fatalError("getLoadedCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let shiftDueDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var shiftDueDatesCallCount: Int { + return shiftDueDatesState.withLock(\.callCount) + } + public var shiftDueDatesHandler: (@Sendable (String) async throws -> ())? { + get { shiftDueDatesState.withLock(\.handler) } + set { shiftDueDatesState.withLock { $0.handler = newValue } } + } + public func shiftDueDates(courseID: String) async throws { + let shiftDueDatesHandler = shiftDueDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let shiftDueDatesHandler = shiftDueDatesHandler { + try await shiftDueDatesHandler(courseID) + } + + } +} + +public final class DatesPersistenceProtocolMock: DatesPersistenceProtocol, @unchecked Sendable { + public init() { } + + + private let loadCourseDatesState = MockoloMutex(MockoloHandlerState [CourseDate]>()) + public var loadCourseDatesCallCount: Int { + return loadCourseDatesState.withLock(\.callCount) + } + public var loadCourseDatesHandler: (@Sendable (Int?, Int?) async throws -> [CourseDate])? { + get { loadCourseDatesState.withLock(\.handler) } + set { loadCourseDatesState.withLock { $0.handler = newValue } } + } + public func loadCourseDates(limit: Int?, offset: Int?) async throws -> [CourseDate] { + let loadCourseDatesHandler = loadCourseDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadCourseDatesHandler = loadCourseDatesHandler { + return try await loadCourseDatesHandler(limit, offset) + } + return [CourseDate]() + } + + private let saveCourseDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var saveCourseDatesCallCount: Int { + return saveCourseDatesState.withLock(\.callCount) + } + public var saveCourseDatesHandler: (@Sendable ([CourseDate], Int) async -> ())? { + get { saveCourseDatesState.withLock(\.handler) } + set { saveCourseDatesState.withLock { $0.handler = newValue } } + } + public func saveCourseDates(dates: [CourseDate], startIndex: Int) async { + let saveCourseDatesHandler = saveCourseDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveCourseDatesHandler = saveCourseDatesHandler { + await saveCourseDatesHandler(dates, startIndex) + } + + } + + private let clearAllCourseDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var clearAllCourseDatesCallCount: Int { + return clearAllCourseDatesState.withLock(\.callCount) + } + public var clearAllCourseDatesHandler: (@Sendable () async -> ())? { + get { clearAllCourseDatesState.withLock(\.handler) } + set { clearAllCourseDatesState.withLock { $0.handler = newValue } } + } + public func clearAllCourseDates() async { + let clearAllCourseDatesHandler = clearAllCourseDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearAllCourseDatesHandler = clearAllCourseDatesHandler { + await clearAllCourseDatesHandler() + } + + } +} + +public final class DatesRepositoryProtocolMock: DatesRepositoryProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseDatesState = MockoloMutex(MockoloHandlerState ([CourseDate], String?)>()) + public var getCourseDatesCallCount: Int { + return getCourseDatesState.withLock(\.callCount) + } + public var getCourseDatesHandler: (@Sendable (Int) async throws -> ([CourseDate], String?))? { + get { getCourseDatesState.withLock(\.handler) } + set { getCourseDatesState.withLock { $0.handler = newValue } } + } + public func getCourseDates(page: Int) async throws -> ([CourseDate], String?) { + let getCourseDatesHandler = getCourseDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDatesHandler = getCourseDatesHandler { + return try await getCourseDatesHandler(page) + } + return ([CourseDate](), nil) + } + + private let getCourseDatesOfflineState = MockoloMutex(MockoloHandlerState [CourseDate]>()) + public var getCourseDatesOfflineCallCount: Int { + return getCourseDatesOfflineState.withLock(\.callCount) + } + public var getCourseDatesOfflineHandler: (@Sendable (Int?, Int?) async throws -> [CourseDate])? { + get { getCourseDatesOfflineState.withLock(\.handler) } + set { getCourseDatesOfflineState.withLock { $0.handler = newValue } } + } + public func getCourseDatesOffline(limit: Int?, offset: Int?) async throws -> [CourseDate] { + let getCourseDatesOfflineHandler = getCourseDatesOfflineState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDatesOfflineHandler = getCourseDatesOfflineHandler { + return try await getCourseDatesOfflineHandler(limit, offset) + } + return [CourseDate]() + } + + private let resetAllRelativeCourseDeadlinesState = MockoloMutex(MockoloHandlerState ()>()) + public var resetAllRelativeCourseDeadlinesCallCount: Int { + return resetAllRelativeCourseDeadlinesState.withLock(\.callCount) + } + public var resetAllRelativeCourseDeadlinesHandler: (@Sendable () async throws -> ())? { + get { resetAllRelativeCourseDeadlinesState.withLock(\.handler) } + set { resetAllRelativeCourseDeadlinesState.withLock { $0.handler = newValue } } + } + public func resetAllRelativeCourseDeadlines() async throws { + let resetAllRelativeCourseDeadlinesHandler = resetAllRelativeCourseDeadlinesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resetAllRelativeCourseDeadlinesHandler = resetAllRelativeCourseDeadlinesHandler { + try await resetAllRelativeCourseDeadlinesHandler() + } + + } +} + +public final class ConnectivityProtocolMock: ConnectivityProtocol, @unchecked Sendable { + public init() { } + public init(isInternetAvaliable: Bool = false, isMobileData: Bool = false) { + self.isInternetAvaliable = isInternetAvaliable + self.isMobileData = isMobileData + } + + + + public var isInternetAvaliable: Bool = false + + + public var isMobileData: Bool = false + + + private var _internetReachableSubject: CurrentValueSubject! + public var internetReachableSubject: CurrentValueSubject { + get { return _internetReachableSubject } + set { _internetReachableSubject = newValue } + } +} + +public final class DownloadManagerProtocolMock: DownloadManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCurrentDownloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var getCurrentDownloadTaskCallCount: Int { + return getCurrentDownloadTaskState.withLock(\.callCount) + } + public var getCurrentDownloadTaskHandler: (@Sendable () async -> DownloadDataTask?)? { + get { getCurrentDownloadTaskState.withLock(\.handler) } + set { getCurrentDownloadTaskState.withLock { $0.handler = newValue } } + } + public func getCurrentDownloadTask() async -> DownloadDataTask? { + let getCurrentDownloadTaskHandler = getCurrentDownloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCurrentDownloadTaskHandler = getCurrentDownloadTaskHandler { + return await getCurrentDownloadTaskHandler() + } + return nil + } + + private let eventPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var eventPublisherCallCount: Int { + return eventPublisherState.withLock(\.callCount) + } + public var eventPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { eventPublisherState.withLock(\.handler) } + set { eventPublisherState.withLock { $0.handler = newValue } } + } + public func eventPublisher() -> AnyPublisher { + let eventPublisherHandler = eventPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let eventPublisherHandler = eventPublisherHandler { + return eventPublisherHandler() + } + fatalError("eventPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([CourseBlock]) async throws -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock]) async throws { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + try await addToDownloadQueueHandler(blocks) + } + + } + + private let getDownloadTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksCallCount: Int { + return getDownloadTasksState.withLock(\.callCount) + } + public var getDownloadTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadTasksState.withLock(\.handler) } + set { getDownloadTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadTasks() async -> [DownloadDataTask] { + let getDownloadTasksHandler = getDownloadTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksHandler = getDownloadTasksHandler { + return await getDownloadTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksForCourseCallCount: Int { + return getDownloadTasksForCourseState.withLock(\.callCount) + } + public var getDownloadTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadTasksForCourseState.withLock(\.handler) } + set { getDownloadTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadTasksForCourseHandler = getDownloadTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksForCourseHandler = getDownloadTasksForCourseHandler { + return await getDownloadTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let cancelDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCallCount: Int { + return cancelDownloadingState.withLock(\.callCount) + } + public var cancelDownloadingHandler: (@Sendable (String, [CourseBlock]) async throws -> ())? { + get { cancelDownloadingState.withLock(\.handler) } + set { cancelDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String, blocks: [CourseBlock]) async throws { + let cancelDownloadingHandler = cancelDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingHandler = cancelDownloadingHandler { + try await cancelDownloadingHandler(courseId, blocks) + } + + } + + private let cancelDownloadingTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingTaskCallCount: Int { + return cancelDownloadingTaskState.withLock(\.callCount) + } + public var cancelDownloadingTaskHandler: (@Sendable (DownloadDataTask) async throws -> ())? { + get { cancelDownloadingTaskState.withLock(\.handler) } + set { cancelDownloadingTaskState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(task: DownloadDataTask) async throws { + let cancelDownloadingTaskHandler = cancelDownloadingTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingTaskHandler = cancelDownloadingTaskHandler { + try await cancelDownloadingTaskHandler(task) + } + + } + + private let cancelDownloadingCourseIdState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCourseIdCallCount: Int { + return cancelDownloadingCourseIdState.withLock(\.callCount) + } + public var cancelDownloadingCourseIdHandler: (@Sendable (String) async throws -> ())? { + get { cancelDownloadingCourseIdState.withLock(\.handler) } + set { cancelDownloadingCourseIdState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String) async throws { + let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdHandler { + try await cancelDownloadingCourseIdHandler(courseId) + } + + } + + private let cancelAllDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelAllDownloadingCallCount: Int { + return cancelAllDownloadingState.withLock(\.callCount) + } + public var cancelAllDownloadingHandler: (@Sendable () async throws -> ())? { + get { cancelAllDownloadingState.withLock(\.handler) } + set { cancelAllDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelAllDownloading() async throws { + let cancelAllDownloadingHandler = cancelAllDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelAllDownloadingHandler = cancelAllDownloadingHandler { + try await cancelAllDownloadingHandler() + } + + } + + private let deleteAllState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllCallCount: Int { + return deleteAllState.withLock(\.callCount) + } + public var deleteAllHandler: (@Sendable () async -> ())? { + get { deleteAllState.withLock(\.handler) } + set { deleteAllState.withLock { $0.handler = newValue } } + } + public func deleteAll() async { + let deleteAllHandler = deleteAllState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllHandler = deleteAllHandler { + await deleteAllHandler() + } + + } + + private let fileUrlState = MockoloMutex(MockoloHandlerState URL?>()) + public var fileUrlCallCount: Int { + return fileUrlState.withLock(\.callCount) + } + public var fileUrlHandler: (@Sendable (String) async -> URL?)? { + get { fileUrlState.withLock(\.handler) } + set { fileUrlState.withLock { $0.handler = newValue } } + } + public func fileUrl(for blockId: String) async -> URL? { + let fileUrlHandler = fileUrlState.withLock { state in + state.callCount += 1 + return state.handler + } + if let fileUrlHandler = fileUrlHandler { + return await fileUrlHandler(blockId) + } + return nil + } + + private let resumeDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var resumeDownloadingCallCount: Int { + return resumeDownloadingState.withLock(\.callCount) + } + public var resumeDownloadingHandler: (@Sendable () async throws -> ())? { + get { resumeDownloadingState.withLock(\.handler) } + set { resumeDownloadingState.withLock { $0.handler = newValue } } + } + public func resumeDownloading() async throws { + let resumeDownloadingHandler = resumeDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resumeDownloadingHandler = resumeDownloadingHandler { + try await resumeDownloadingHandler() + } + + } + + private let isLargeVideosSizeState = MockoloMutex(MockoloHandlerState Bool>()) + public var isLargeVideosSizeCallCount: Int { + return isLargeVideosSizeState.withLock(\.callCount) + } + public var isLargeVideosSizeHandler: (@Sendable ([CourseBlock]) async -> Bool)? { + get { isLargeVideosSizeState.withLock(\.handler) } + set { isLargeVideosSizeState.withLock { $0.handler = newValue } } + } + public func isLargeVideosSize(blocks: [CourseBlock]) async -> Bool { + let isLargeVideosSizeHandler = isLargeVideosSizeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isLargeVideosSizeHandler = isLargeVideosSizeHandler { + return await isLargeVideosSizeHandler(blocks) + } + return false + } + + private let removeAppSupportDirectoryUnusedContentState = MockoloMutex(MockoloHandlerState ()>()) + public var removeAppSupportDirectoryUnusedContentCallCount: Int { + return removeAppSupportDirectoryUnusedContentState.withLock(\.callCount) + } + public var removeAppSupportDirectoryUnusedContentHandler: (@Sendable () -> ())? { + get { removeAppSupportDirectoryUnusedContentState.withLock(\.handler) } + set { removeAppSupportDirectoryUnusedContentState.withLock { $0.handler = newValue } } + } + public func removeAppSupportDirectoryUnusedContent() { + let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentHandler { + removeAppSupportDirectoryUnusedContentHandler() + } + + } + + private let deleteState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteCallCount: Int { + return deleteState.withLock(\.callCount) + } + public var deleteHandler: (@Sendable ([CourseBlock], String) async -> ())? { + get { deleteState.withLock(\.handler) } + set { deleteState.withLock { $0.handler = newValue } } + } + public func delete(blocks: [CourseBlock], courseId: String) async { + let deleteHandler = deleteState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteHandler = deleteHandler { + await deleteHandler(blocks, courseId) + } + + } + + private let downloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadTaskCallCount: Int { + return downloadTaskState.withLock(\.callCount) + } + public var downloadTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadTaskState.withLock(\.handler) } + set { downloadTaskState.withLock { $0.handler = newValue } } + } + public func downloadTask(for blockId: String) async -> DownloadDataTask? { + let downloadTaskHandler = downloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadTaskHandler = downloadTaskHandler { + return await downloadTaskHandler(blockId) + } + return nil + } + + private let getFreeDiskSpaceState = MockoloMutex(MockoloHandlerState Int?>()) + public var getFreeDiskSpaceCallCount: Int { + return getFreeDiskSpaceState.withLock(\.callCount) + } + public var getFreeDiskSpaceHandler: (@Sendable () -> Int?)? { + get { getFreeDiskSpaceState.withLock(\.handler) } + set { getFreeDiskSpaceState.withLock { $0.handler = newValue } } + } + public func getFreeDiskSpace() -> Int? { + let getFreeDiskSpaceHandler = getFreeDiskSpaceState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getFreeDiskSpaceHandler = getFreeDiskSpaceHandler { + return getFreeDiskSpaceHandler() + } + return nil + } +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { + print("At \(function), the captured arguments are not Sendable, it is not concurrency-safe.") +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { +} + +/// Will be replaced to `Synchronization.Mutex` in future. +fileprivate final class MockoloMutex: @unchecked Sendable { + private let lock = NSLock() + private var value: Value + init(_ initialValue: Value) { + self.value = initialValue + } +#if compiler(>=6.0) + borrowing func withLock(_ body: (inout sending Value) throws(E) -> Result) throws(E) -> sending Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#else + func withLock(_ body: (inout Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#endif +} + +fileprivate struct MockoloUnsafeTransfer: @unchecked Sendable { + var value: Value + init(_ value: Value) { + self.value = value + } +} + +fileprivate struct MockoloHandlerState { + var argValues: [MockoloUnsafeTransfer] = [] + var handler: Handler? = nil + var callCount: Int = 0 +} + diff --git a/AppDates/Mockfile b/AppDates/Mockfile deleted file mode 100644 index 940ff582b..000000000 --- a/AppDates/Mockfile +++ /dev/null @@ -1,18 +0,0 @@ -sourceryCommand: mint run krzysztofzablocki/Sourcery@2.1.2 sourcery -sourceryTemplate: ../MockTemplate.swifttemplate -unit.tests.mock: - sources: - include: - - ./../Core - - ./AppDates - exclude: [] - output: ./AppDatesTests/AppDatesMock.generated.swift - targets: - - MyAppUnitTests - import: - - Core - - AppDates - - Foundation - - SwiftUI - - Combine - - OEXFoundation \ No newline at end of file diff --git a/Authorization/Authorization.xcodeproj/project.pbxproj b/Authorization/Authorization.xcodeproj/project.pbxproj index 97ff10c93..08d312520 100644 --- a/Authorization/Authorization.xcodeproj/project.pbxproj +++ b/Authorization/Authorization.xcodeproj/project.pbxproj @@ -11,7 +11,6 @@ 02066B462906D72F00F4307E /* SignUpViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02066B452906D72F00F4307E /* SignUpViewModel.swift */; }; 020C31CB290BF49900D6DEA2 /* FieldsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020C31CA290BF49900D6DEA2 /* FieldsView.swift */; }; 022D0482297442BA00E0059B /* SignUpViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022D0481297442BA00E0059B /* SignUpViewModelTests.swift */; }; - 022D04962976DA6500E0059B /* AuthorizationMock.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022D04952976DA6500E0059B /* AuthorizationMock.generated.swift */; }; 025F40E029D1E2FC0064C183 /* ResetPasswordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025F40DF29D1E2FC0064C183 /* ResetPasswordView.swift */; }; 025F40E229D360E20064C183 /* ResetPasswordViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025F40E129D360E20064C183 /* ResetPasswordViewModel.swift */; }; 02A2ACDB2A4B016100FBBBBB /* AuthorizationAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A2ACDA2A4B016100FBBBBB /* AuthorizationAnalytics.swift */; }; @@ -30,6 +29,7 @@ 99C1654D2C0C4F2F00DC384D /* SSOHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99C1654C2C0C4F2F00DC384D /* SSOHelper.swift */; }; 99C1654F2C0C4F5900DC384D /* SSOWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99C1654E2C0C4F5900DC384D /* SSOWebView.swift */; }; 99C165512C0C4F7B00DC384D /* SSOWebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99C165502C0C4F7B00DC384D /* SSOWebViewModel.swift */; }; + A5B468112F29C845002A4ECA /* AuthorizationMocks.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B4680F2F29C845002A4ECA /* AuthorizationMocks.generated.swift */; }; BA8B3A322AD5487300D25EF5 /* SocialAuthView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA8B3A312AD5487300D25EF5 /* SocialAuthView.swift */; }; BADB3F552AD6DFC3004D5CFA /* SocialAuthViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADB3F542AD6DFC3004D5CFA /* SocialAuthViewModel.swift */; }; CE7CAF2D2CC155BE00E0AC9D /* OEXFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CE7CAF2C2CC155BE00E0AC9D /* OEXFoundation */; }; @@ -75,7 +75,6 @@ 02066B452906D72F00F4307E /* SignUpViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpViewModel.swift; sourceTree = ""; }; 020C31CA290BF49900D6DEA2 /* FieldsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FieldsView.swift; sourceTree = ""; }; 022D0481297442BA00E0059B /* SignUpViewModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpViewModelTests.swift; sourceTree = ""; }; - 022D04952976DA6500E0059B /* AuthorizationMock.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthorizationMock.generated.swift; sourceTree = ""; }; 025F40DF29D1E2FC0064C183 /* ResetPasswordView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetPasswordView.swift; sourceTree = ""; }; 025F40E129D360E20064C183 /* ResetPasswordViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetPasswordViewModel.swift; sourceTree = ""; }; 02A2ACDA2A4B016100FBBBBB /* AuthorizationAnalytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorizationAnalytics.swift; sourceTree = ""; }; @@ -108,6 +107,7 @@ 99C1654E2C0C4F5900DC384D /* SSOWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSOWebView.swift; sourceTree = ""; }; 99C165502C0C4F7B00DC384D /* SSOWebViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSOWebViewModel.swift; sourceTree = ""; }; 9BF6A1004A955E24527FCF0F /* Pods-App-Authorization-AuthorizationTests.releaseprod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Authorization-AuthorizationTests.releaseprod.xcconfig"; path = "Target Support Files/Pods-App-Authorization-AuthorizationTests/Pods-App-Authorization-AuthorizationTests.releaseprod.xcconfig"; sourceTree = ""; }; + A5B4680F2F29C845002A4ECA /* AuthorizationMocks.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorizationMocks.generated.swift; sourceTree = ""; }; A99D45203C981893C104053A /* Pods-App-Authorization-AuthorizationTests.releasestage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Authorization-AuthorizationTests.releasestage.xcconfig"; path = "Target Support Files/Pods-App-Authorization-AuthorizationTests/Pods-App-Authorization-AuthorizationTests.releasestage.xcconfig"; sourceTree = ""; }; BA8B3A312AD5487300D25EF5 /* SocialAuthView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialAuthView.swift; sourceTree = ""; }; BADB3F542AD6DFC3004D5CFA /* SocialAuthViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialAuthViewModel.swift; sourceTree = ""; }; @@ -203,7 +203,7 @@ 07169455296D913400E3DED6 /* AuthorizationTests */ = { isa = PBXGroup; children = ( - 022D04952976DA6500E0059B /* AuthorizationMock.generated.swift */, + A5B468102F29C845002A4ECA /* Generated */, 07169483296EC3CC00E3DED6 /* Presentation */, ); path = AuthorizationTests; @@ -321,6 +321,14 @@ path = SSO; sourceTree = ""; }; + A5B468102F29C845002A4ECA /* Generated */ = { + isa = PBXGroup; + children = ( + A5B4680F2F29C845002A4ECA /* AuthorizationMocks.generated.swift */, + ); + path = Generated; + sourceTree = ""; + }; BA8B3A302AD5485100D25EF5 /* SocialAuth */ = { isa = PBXGroup; children = ( @@ -381,7 +389,6 @@ 07169450296D913300E3DED6 /* Sources */, 07169451296D913300E3DED6 /* Frameworks */, 07169452296D913300E3DED6 /* Resources */, - 95C8CAF0620ABBBAD7ED66D6 /* [CP] Copy Pods Resources */, CE7CAF2F2CC155BE00E0AC9D /* Embed Frameworks */, ); buildRules = ( @@ -518,23 +525,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 95C8CAF0620ABBBAD7ED66D6 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Authorization-AuthorizationTests/Pods-App-Authorization-AuthorizationTests-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Authorization-AuthorizationTests/Pods-App-Authorization-AuthorizationTests-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App-Authorization-AuthorizationTests/Pods-App-Authorization-AuthorizationTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; FAD36FCACFE4B45E3668B2AA /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -564,9 +554,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 022D04962976DA6500E0059B /* AuthorizationMock.generated.swift in Sources */, 022D0482297442BA00E0059B /* SignUpViewModelTests.swift in Sources */, 07169464296D96DD00E3DED6 /* SignInViewModelTests.swift in Sources */, + A5B468112F29C845002A4ECA /* AuthorizationMocks.generated.swift in Sources */, 02E0618429DC2373006E9024 /* ResetPasswordViewModelTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Authorization/Authorization/Presentation/AuthorizationAnalytics.swift b/Authorization/Authorization/Presentation/AuthorizationAnalytics.swift index 103d64a18..d7d62c167 100644 --- a/Authorization/Authorization/Presentation/AuthorizationAnalytics.swift +++ b/Authorization/Authorization/Presentation/AuthorizationAnalytics.swift @@ -33,7 +33,7 @@ public enum SocialAuthMethod: String { case apple } -//sourcery: AutoMockable +/// @mockable public protocol AuthorizationAnalytics { func identify(id: String, username: String, email: String) func userLogin(method: AuthMethod) @@ -49,8 +49,9 @@ public protocol AuthorizationAnalytics { } #if DEBUG -class AuthorizationAnalyticsMock: AuthorizationAnalytics { - func identify(id: String, username: String, email: String) {} +public class AuthorizationAnalyticsMock: AuthorizationAnalytics { + public init() {} + public func identify(id: String, username: String, email: String) {} public func userLogin(method: AuthMethod) {} public func registerClicked() {} public func signInClicked() {} diff --git a/Authorization/Authorization/Presentation/AuthorizationRouter.swift b/Authorization/Authorization/Presentation/AuthorizationRouter.swift index cf2289b12..8d2393e07 100644 --- a/Authorization/Authorization/Presentation/AuthorizationRouter.swift +++ b/Authorization/Authorization/Presentation/AuthorizationRouter.swift @@ -8,7 +8,7 @@ import Foundation import Core -//sourcery: AutoMockable +/// @mockable @MainActor public protocol AuthorizationRouter: BaseRouter { func showUpdateRequiredView(showAccountLink: Bool) diff --git a/Authorization/Authorization/Presentation/SocialAuth/SocialAuthViewModel.swift b/Authorization/Authorization/Presentation/SocialAuth/SocialAuthViewModel.swift index 8ebd6e35e..b4163a588 100644 --- a/Authorization/Authorization/Presentation/SocialAuth/SocialAuthViewModel.swift +++ b/Authorization/Authorization/Presentation/SocialAuth/SocialAuthViewModel.swift @@ -10,7 +10,7 @@ import Core import AuthenticationServices import FacebookLogin import GoogleSignIn -import MSAL +//import MSAL import Swinject enum SocialAuthDetails { diff --git a/Authorization/AuthorizationTests/AuthorizationMock.generated.swift b/Authorization/AuthorizationTests/AuthorizationMock.generated.swift deleted file mode 100644 index d77065633..000000000 --- a/Authorization/AuthorizationTests/AuthorizationMock.generated.swift +++ /dev/null @@ -1,5400 +0,0 @@ -// Generated using Sourcery 2.1.2 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT - - -// Generated with SwiftyMocky 4.2.0 -// Required Sourcery: 1.8.0 - - -import SwiftyMocky -import XCTest -import Core -import Authorization -import Foundation -import SwiftUI -import Combine -import OEXFoundation - - -// MARK: - AuthInteractorProtocol - -open class AuthInteractorProtocolMock: AuthInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - @discardableResult - open func login(username: String, password: String) throws -> User { - addInvocation(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) - let perform = methodPerformValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) as? (String, String) -> Void - perform?(`username`, `password`) - var __value: User - do { - __value = try methodReturnValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(username: String, password: String). Use given") - Failure("Stub return value not specified for login(username: String, password: String). Use given") - } catch { - throw error - } - return __value - } - - @discardableResult - open func login(externalToken: String, backend: String) throws -> User { - addInvocation(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) - let perform = methodPerformValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) as? (String, String) -> Void - perform?(`externalToken`, `backend`) - var __value: User - do { - __value = try methodReturnValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - Failure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - } catch { - throw error - } - return __value - } - - open func login(ssoToken: String) throws -> User { - addInvocation(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) - let perform = methodPerformValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) as? (String) -> Void - perform?(`ssoToken`) - var __value: User - do { - __value = try methodReturnValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(ssoToken: String). Use given") - Failure("Stub return value not specified for login(ssoToken: String). Use given") - } catch { - throw error - } - return __value - } - - open func resetPassword(email: String) throws -> ResetPassword { - addInvocation(.m_resetPassword__email_email(Parameter.value(`email`))) - let perform = methodPerformValue(.m_resetPassword__email_email(Parameter.value(`email`))) as? (String) -> Void - perform?(`email`) - var __value: ResetPassword - do { - __value = try methodReturnValue(.m_resetPassword__email_email(Parameter.value(`email`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for resetPassword(email: String). Use given") - Failure("Stub return value not specified for resetPassword(email: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCookies(force: Bool) throws { - addInvocation(.m_getCookies__force_force(Parameter.value(`force`))) - let perform = methodPerformValue(.m_getCookies__force_force(Parameter.value(`force`))) as? (Bool) -> Void - perform?(`force`) - do { - _ = try methodReturnValue(.m_getCookies__force_force(Parameter.value(`force`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getRegistrationFields() throws -> [PickerFields] { - addInvocation(.m_getRegistrationFields) - let perform = methodPerformValue(.m_getRegistrationFields) as? () -> Void - perform?() - var __value: [PickerFields] - do { - __value = try methodReturnValue(.m_getRegistrationFields).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getRegistrationFields(). Use given") - Failure("Stub return value not specified for getRegistrationFields(). Use given") - } catch { - throw error - } - return __value - } - - open func registerUser(fields: [String: String], isSocial: Bool) throws -> User { - addInvocation(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) - let perform = methodPerformValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) as? ([String: String], Bool) -> Void - perform?(`fields`, `isSocial`) - var __value: User - do { - __value = try methodReturnValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - Failure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - } catch { - throw error - } - return __value - } - - open func validateRegistrationFields(fields: [String: String]) throws -> [String: String] { - addInvocation(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) - let perform = methodPerformValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) as? ([String: String]) -> Void - perform?(`fields`) - var __value: [String: String] - do { - __value = try methodReturnValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - Failure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_login__username_usernamepassword_password(Parameter, Parameter) - case m_login__externalToken_externalTokenbackend_backend(Parameter, Parameter) - case m_login__ssoToken_ssoToken(Parameter) - case m_resetPassword__email_email(Parameter) - case m_getCookies__force_force(Parameter) - case m_getRegistrationFields - case m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>, Parameter) - case m_validateRegistrationFields__fields_fields(Parameter<[String: String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_login__username_usernamepassword_password(let lhsUsername, let lhsPassword), .m_login__username_usernamepassword_password(let rhsUsername, let rhsPassword)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsername, rhs: rhsUsername, with: matcher), lhsUsername, rhsUsername, "username")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPassword, rhs: rhsPassword, with: matcher), lhsPassword, rhsPassword, "password")) - return Matcher.ComparisonResult(results) - - case (.m_login__externalToken_externalTokenbackend_backend(let lhsExternaltoken, let lhsBackend), .m_login__externalToken_externalTokenbackend_backend(let rhsExternaltoken, let rhsBackend)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsExternaltoken, rhs: rhsExternaltoken, with: matcher), lhsExternaltoken, rhsExternaltoken, "externalToken")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBackend, rhs: rhsBackend, with: matcher), lhsBackend, rhsBackend, "backend")) - return Matcher.ComparisonResult(results) - - case (.m_login__ssoToken_ssoToken(let lhsSsotoken), .m_login__ssoToken_ssoToken(let rhsSsotoken)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSsotoken, rhs: rhsSsotoken, with: matcher), lhsSsotoken, rhsSsotoken, "ssoToken")) - return Matcher.ComparisonResult(results) - - case (.m_resetPassword__email_email(let lhsEmail), .m_resetPassword__email_email(let rhsEmail)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEmail, rhs: rhsEmail, with: matcher), lhsEmail, rhsEmail, "email")) - return Matcher.ComparisonResult(results) - - case (.m_getCookies__force_force(let lhsForce), .m_getCookies__force_force(let rhsForce)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsForce, rhs: rhsForce, with: matcher), lhsForce, rhsForce, "force")) - return Matcher.ComparisonResult(results) - - case (.m_getRegistrationFields, .m_getRegistrationFields): return .match - - case (.m_registerUser__fields_fieldsisSocial_isSocial(let lhsFields, let lhsIssocial), .m_registerUser__fields_fieldsisSocial_isSocial(let rhsFields, let rhsIssocial)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIssocial, rhs: rhsIssocial, with: matcher), lhsIssocial, rhsIssocial, "isSocial")) - return Matcher.ComparisonResult(results) - - case (.m_validateRegistrationFields__fields_fields(let lhsFields), .m_validateRegistrationFields__fields_fields(let rhsFields)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_login__username_usernamepassword_password(p0, p1): return p0.intValue + p1.intValue - case let .m_login__externalToken_externalTokenbackend_backend(p0, p1): return p0.intValue + p1.intValue - case let .m_login__ssoToken_ssoToken(p0): return p0.intValue - case let .m_resetPassword__email_email(p0): return p0.intValue - case let .m_getCookies__force_force(p0): return p0.intValue - case .m_getRegistrationFields: return 0 - case let .m_registerUser__fields_fieldsisSocial_isSocial(p0, p1): return p0.intValue + p1.intValue - case let .m_validateRegistrationFields__fields_fields(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_login__username_usernamepassword_password: return ".login(username:password:)" - case .m_login__externalToken_externalTokenbackend_backend: return ".login(externalToken:backend:)" - case .m_login__ssoToken_ssoToken: return ".login(ssoToken:)" - case .m_resetPassword__email_email: return ".resetPassword(email:)" - case .m_getCookies__force_force: return ".getCookies(force:)" - case .m_getRegistrationFields: return ".getRegistrationFields()" - case .m_registerUser__fields_fieldsisSocial_isSocial: return ".registerUser(fields:isSocial:)" - case .m_validateRegistrationFields__fields_fields: return ".validateRegistrationFields(fields:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - @discardableResult - public static func login(username: Parameter, password: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func login(ssoToken: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func resetPassword(email: Parameter, willReturn: ResetPassword...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getRegistrationFields(willReturn: [PickerFields]...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willReturn: [String: String]...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func login(ssoToken: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func login(ssoToken: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func resetPassword(email: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resetPassword(email: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (ResetPassword).self) - willProduce(stubber) - return given - } - public static func getCookies(force: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCookies(force: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func getRegistrationFields(willThrow: Error...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getRegistrationFields(willProduce: (StubberThrows<[PickerFields]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([PickerFields]).self) - willProduce(stubber) - return given - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willProduce: (StubberThrows<[String: String]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([String: String]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - @discardableResult - public static func login(username: Parameter, password: Parameter) -> Verify { return Verify(method: .m_login__username_usernamepassword_password(`username`, `password`))} - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter) -> Verify { return Verify(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`))} - public static func login(ssoToken: Parameter) -> Verify { return Verify(method: .m_login__ssoToken_ssoToken(`ssoToken`))} - public static func resetPassword(email: Parameter) -> Verify { return Verify(method: .m_resetPassword__email_email(`email`))} - public static func getCookies(force: Parameter) -> Verify { return Verify(method: .m_getCookies__force_force(`force`))} - public static func getRegistrationFields() -> Verify { return Verify(method: .m_getRegistrationFields)} - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter) -> Verify { return Verify(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`))} - public static func validateRegistrationFields(fields: Parameter<[String: String]>) -> Verify { return Verify(method: .m_validateRegistrationFields__fields_fields(`fields`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - @discardableResult - public static func login(username: Parameter, password: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__username_usernamepassword_password(`username`, `password`), performs: perform) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), performs: perform) - } - public static func login(ssoToken: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_login__ssoToken_ssoToken(`ssoToken`), performs: perform) - } - public static func resetPassword(email: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_resetPassword__email_email(`email`), performs: perform) - } - public static func getCookies(force: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_getCookies__force_force(`force`), performs: perform) - } - public static func getRegistrationFields(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getRegistrationFields, performs: perform) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, perform: @escaping ([String: String], Bool) -> Void) -> Perform { - return Perform(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), performs: perform) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, perform: @escaping ([String: String]) -> Void) -> Perform { - return Perform(method: .m_validateRegistrationFields__fields_fields(`fields`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - AuthorizationAnalytics - -open class AuthorizationAnalyticsMock: AuthorizationAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func identify(id: String, username: String, email: String) { - addInvocation(.m_identify__id_idusername_usernameemail_email(Parameter.value(`id`), Parameter.value(`username`), Parameter.value(`email`))) - let perform = methodPerformValue(.m_identify__id_idusername_usernameemail_email(Parameter.value(`id`), Parameter.value(`username`), Parameter.value(`email`))) as? (String, String, String) -> Void - perform?(`id`, `username`, `email`) - } - - open func userLogin(method: AuthMethod) { - addInvocation(.m_userLogin__method_method(Parameter.value(`method`))) - let perform = methodPerformValue(.m_userLogin__method_method(Parameter.value(`method`))) as? (AuthMethod) -> Void - perform?(`method`) - } - - open func registerClicked() { - addInvocation(.m_registerClicked) - let perform = methodPerformValue(.m_registerClicked) as? () -> Void - perform?() - } - - open func signInClicked() { - addInvocation(.m_signInClicked) - let perform = methodPerformValue(.m_signInClicked) as? () -> Void - perform?() - } - - open func userSignInClicked() { - addInvocation(.m_userSignInClicked) - let perform = methodPerformValue(.m_userSignInClicked) as? () -> Void - perform?() - } - - open func createAccountClicked() { - addInvocation(.m_createAccountClicked) - let perform = methodPerformValue(.m_createAccountClicked) as? () -> Void - perform?() - } - - open func registrationSuccess(method: String) { - addInvocation(.m_registrationSuccess__method_method(Parameter.value(`method`))) - let perform = methodPerformValue(.m_registrationSuccess__method_method(Parameter.value(`method`))) as? (String) -> Void - perform?(`method`) - } - - open func forgotPasswordClicked() { - addInvocation(.m_forgotPasswordClicked) - let perform = methodPerformValue(.m_forgotPasswordClicked) as? () -> Void - perform?() - } - - open func resetPasswordClicked() { - addInvocation(.m_resetPasswordClicked) - let perform = methodPerformValue(.m_resetPasswordClicked) as? () -> Void - perform?() - } - - open func resetPassword(success: Bool) { - addInvocation(.m_resetPassword__success_success(Parameter.value(`success`))) - let perform = methodPerformValue(.m_resetPassword__success_success(Parameter.value(`success`))) as? (Bool) -> Void - perform?(`success`) - } - - open func authTrackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_authTrackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_authTrackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - - fileprivate enum MethodType { - case m_identify__id_idusername_usernameemail_email(Parameter, Parameter, Parameter) - case m_userLogin__method_method(Parameter) - case m_registerClicked - case m_signInClicked - case m_userSignInClicked - case m_createAccountClicked - case m_registrationSuccess__method_method(Parameter) - case m_forgotPasswordClicked - case m_resetPasswordClicked - case m_resetPassword__success_success(Parameter) - case m_authTrackScreenEvent__eventbiValue_biValue(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_identify__id_idusername_usernameemail_email(let lhsId, let lhsUsername, let lhsEmail), .m_identify__id_idusername_usernameemail_email(let rhsId, let rhsUsername, let rhsEmail)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsId, rhs: rhsId, with: matcher), lhsId, rhsId, "id")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsername, rhs: rhsUsername, with: matcher), lhsUsername, rhsUsername, "username")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEmail, rhs: rhsEmail, with: matcher), lhsEmail, rhsEmail, "email")) - return Matcher.ComparisonResult(results) - - case (.m_userLogin__method_method(let lhsMethod), .m_userLogin__method_method(let rhsMethod)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsMethod, rhs: rhsMethod, with: matcher), lhsMethod, rhsMethod, "method")) - return Matcher.ComparisonResult(results) - - case (.m_registerClicked, .m_registerClicked): return .match - - case (.m_signInClicked, .m_signInClicked): return .match - - case (.m_userSignInClicked, .m_userSignInClicked): return .match - - case (.m_createAccountClicked, .m_createAccountClicked): return .match - - case (.m_registrationSuccess__method_method(let lhsMethod), .m_registrationSuccess__method_method(let rhsMethod)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsMethod, rhs: rhsMethod, with: matcher), lhsMethod, rhsMethod, "method")) - return Matcher.ComparisonResult(results) - - case (.m_forgotPasswordClicked, .m_forgotPasswordClicked): return .match - - case (.m_resetPasswordClicked, .m_resetPasswordClicked): return .match - - case (.m_resetPassword__success_success(let lhsSuccess), .m_resetPassword__success_success(let rhsSuccess)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSuccess, rhs: rhsSuccess, with: matcher), lhsSuccess, rhsSuccess, "success")) - return Matcher.ComparisonResult(results) - - case (.m_authTrackScreenEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_authTrackScreenEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_identify__id_idusername_usernameemail_email(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_userLogin__method_method(p0): return p0.intValue - case .m_registerClicked: return 0 - case .m_signInClicked: return 0 - case .m_userSignInClicked: return 0 - case .m_createAccountClicked: return 0 - case let .m_registrationSuccess__method_method(p0): return p0.intValue - case .m_forgotPasswordClicked: return 0 - case .m_resetPasswordClicked: return 0 - case let .m_resetPassword__success_success(p0): return p0.intValue - case let .m_authTrackScreenEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_identify__id_idusername_usernameemail_email: return ".identify(id:username:email:)" - case .m_userLogin__method_method: return ".userLogin(method:)" - case .m_registerClicked: return ".registerClicked()" - case .m_signInClicked: return ".signInClicked()" - case .m_userSignInClicked: return ".userSignInClicked()" - case .m_createAccountClicked: return ".createAccountClicked()" - case .m_registrationSuccess__method_method: return ".registrationSuccess(method:)" - case .m_forgotPasswordClicked: return ".forgotPasswordClicked()" - case .m_resetPasswordClicked: return ".resetPasswordClicked()" - case .m_resetPassword__success_success: return ".resetPassword(success:)" - case .m_authTrackScreenEvent__eventbiValue_biValue: return ".authTrackScreenEvent(_:biValue:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func identify(id: Parameter, username: Parameter, email: Parameter) -> Verify { return Verify(method: .m_identify__id_idusername_usernameemail_email(`id`, `username`, `email`))} - public static func userLogin(method: Parameter) -> Verify { return Verify(method: .m_userLogin__method_method(`method`))} - public static func registerClicked() -> Verify { return Verify(method: .m_registerClicked)} - public static func signInClicked() -> Verify { return Verify(method: .m_signInClicked)} - public static func userSignInClicked() -> Verify { return Verify(method: .m_userSignInClicked)} - public static func createAccountClicked() -> Verify { return Verify(method: .m_createAccountClicked)} - public static func registrationSuccess(method: Parameter) -> Verify { return Verify(method: .m_registrationSuccess__method_method(`method`))} - public static func forgotPasswordClicked() -> Verify { return Verify(method: .m_forgotPasswordClicked)} - public static func resetPasswordClicked() -> Verify { return Verify(method: .m_resetPasswordClicked)} - public static func resetPassword(success: Parameter) -> Verify { return Verify(method: .m_resetPassword__success_success(`success`))} - public static func authTrackScreenEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_authTrackScreenEvent__eventbiValue_biValue(`event`, `biValue`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func identify(id: Parameter, username: Parameter, email: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_identify__id_idusername_usernameemail_email(`id`, `username`, `email`), performs: perform) - } - public static func userLogin(method: Parameter, perform: @escaping (AuthMethod) -> Void) -> Perform { - return Perform(method: .m_userLogin__method_method(`method`), performs: perform) - } - public static func registerClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_registerClicked, performs: perform) - } - public static func signInClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_signInClicked, performs: perform) - } - public static func userSignInClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_userSignInClicked, performs: perform) - } - public static func createAccountClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_createAccountClicked, performs: perform) - } - public static func registrationSuccess(method: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_registrationSuccess__method_method(`method`), performs: perform) - } - public static func forgotPasswordClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_forgotPasswordClicked, performs: perform) - } - public static func resetPasswordClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_resetPasswordClicked, performs: perform) - } - public static func resetPassword(success: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_resetPassword__success_success(`success`), performs: perform) - } - public static func authTrackScreenEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_authTrackScreenEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - AuthorizationRouter -@MainActor -open class AuthorizationRouterMock: AuthorizationRouter, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func showUpdateRequiredView(showAccountLink: Bool) { - addInvocation(.m_showUpdateRequiredView__showAccountLink_showAccountLink(Parameter.value(`showAccountLink`))) - let perform = methodPerformValue(.m_showUpdateRequiredView__showAccountLink_showAccountLink(Parameter.value(`showAccountLink`))) as? (Bool) -> Void - perform?(`showAccountLink`) - } - - open func backToRoot(animated: Bool) { - addInvocation(.m_backToRoot__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_backToRoot__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func back(animated: Bool) { - addInvocation(.m_back__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_back__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func backWithFade() { - addInvocation(.m_backWithFade) - let perform = methodPerformValue(.m_backWithFade) as? () -> Void - perform?() - } - - open func dismiss(animated: Bool) { - addInvocation(.m_dismiss__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_dismiss__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func removeLastView(controllers: Int) { - addInvocation(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) - let perform = methodPerformValue(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) as? (Int) -> Void - perform?(`controllers`) - } - - open func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { - addInvocation(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) - let perform = methodPerformValue(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) as? (LogistrationSourceScreen, PostLoginData?) -> Void - perform?(`sourceScreen`, `postLoginData`) - } - - open func showStartupScreen() { - addInvocation(.m_showStartupScreen) - let perform = methodPerformValue(.m_showStartupScreen) as? () -> Void - perform?() - } - - open func showLoginScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showForgotPasswordScreen() { - addInvocation(.m_showForgotPasswordScreen) - let perform = methodPerformValue(.m_showForgotPasswordScreen) as? () -> Void - perform?() - } - - open func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) as? (String?, LogistrationSourceScreen) -> Void - perform?(`searchQuery`, `sourceScreen`) - } - - open func showWebBrowser(title: String, url: URL) { - addInvocation(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) - let perform = methodPerformValue(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) as? (String, URL) -> Void - perform?(`title`, `url`) - } - - open func showSSOWebBrowser(title: String) { - addInvocation(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) - let perform = methodPerformValue(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) as? (String) -> Void - perform?(`title`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) as? (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void - perform?(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) as? (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void - perform?(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { - addInvocation(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) as? (UIModalTransitionStyle, any View, (() -> Void)?) -> Void - perform?(`transitionStyle`, `view`, `completion`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { - addInvocation(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) as? (UIModalTransitionStyle, Bool, () -> any View) -> Void - perform?(`transitionStyle`, `animated`, `content`) - } - - - fileprivate enum MethodType { - case m_showUpdateRequiredView__showAccountLink_showAccountLink(Parameter) - case m_backToRoot__animated_animated(Parameter) - case m_back__animated_animated(Parameter) - case m_backWithFade - case m_dismiss__animated_animated(Parameter) - case m_removeLastView__controllers_controllers(Parameter) - case m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter, Parameter) - case m_showStartupScreen - case m_showLoginScreen__sourceScreen_sourceScreen(Parameter) - case m_showRegisterScreen__sourceScreen_sourceScreen(Parameter) - case m_showForgotPasswordScreen - case m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter, Parameter) - case m_showWebBrowser__title_titleurl_url(Parameter, Parameter) - case m_showSSOWebBrowser__title_title(Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter<() -> Void>) - case m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter, Parameter, Parameter<(() -> Void)?>) - case m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter, Parameter, Parameter<() -> any View>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_showUpdateRequiredView__showAccountLink_showAccountLink(let lhsShowaccountlink), .m_showUpdateRequiredView__showAccountLink_showAccountLink(let rhsShowaccountlink)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsShowaccountlink, rhs: rhsShowaccountlink, with: matcher), lhsShowaccountlink, rhsShowaccountlink, "showAccountLink")) - return Matcher.ComparisonResult(results) - - case (.m_backToRoot__animated_animated(let lhsAnimated), .m_backToRoot__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_back__animated_animated(let lhsAnimated), .m_back__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_backWithFade, .m_backWithFade): return .match - - case (.m_dismiss__animated_animated(let lhsAnimated), .m_dismiss__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_removeLastView__controllers_controllers(let lhsControllers), .m_removeLastView__controllers_controllers(let rhsControllers)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsControllers, rhs: rhsControllers, with: matcher), lhsControllers, rhsControllers, "controllers")) - return Matcher.ComparisonResult(results) - - case (.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let lhsSourcescreen, let lhsPostlogindata), .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let rhsSourcescreen, let rhsPostlogindata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPostlogindata, rhs: rhsPostlogindata, with: matcher), lhsPostlogindata, rhsPostlogindata, "postLoginData")) - return Matcher.ComparisonResult(results) - - case (.m_showStartupScreen, .m_showStartupScreen): return .match - - case (.m_showLoginScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showLoginScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showRegisterScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showRegisterScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showForgotPasswordScreen, .m_showForgotPasswordScreen): return .match - - case (.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let lhsSearchquery, let lhsSourcescreen), .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let rhsSearchquery, let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchquery, rhs: rhsSearchquery, with: matcher), lhsSearchquery, rhsSearchquery, "searchQuery")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showWebBrowser__title_titleurl_url(let lhsTitle, let lhsUrl), .m_showWebBrowser__title_titleurl_url(let rhsTitle, let rhsUrl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - return Matcher.ComparisonResult(results) - - case (.m_showSSOWebBrowser__title_title(let lhsTitle), .m_showSSOWebBrowser__title_title(let rhsTitle)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let lhsAlerttitle, let lhsAlertmessage, let lhsPositiveaction, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsType), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let rhsAlerttitle, let rhsAlertmessage, let rhsPositiveaction, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPositiveaction, rhs: rhsPositiveaction, with: matcher), lhsPositiveaction, rhsPositiveaction, "positiveAction")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let lhsAlerttitle, let lhsAlertmessage, let lhsNextsectionname, let lhsAction, let lhsImage, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsNextsectiontapped), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let rhsAlerttitle, let rhsAlertmessage, let rhsNextsectionname, let rhsAction, let rhsImage, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsNextsectiontapped)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectionname, rhs: rhsNextsectionname, with: matcher), lhsNextsectionname, rhsNextsectionname, "nextSectionName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsImage, rhs: rhsImage, with: matcher), lhsImage, rhsImage, "image")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectiontapped, rhs: rhsNextsectiontapped, with: matcher), lhsNextsectiontapped, rhsNextsectiontapped, "nextSectionTapped")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let lhsTransitionstyle, let lhsView, let lhsCompletion), .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let rhsTransitionstyle, let rhsView, let rhsCompletion)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsView, rhs: rhsView, with: matcher), lhsView, rhsView, "view")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCompletion, rhs: rhsCompletion, with: matcher), lhsCompletion, rhsCompletion, "completion")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let lhsTransitionstyle, let lhsAnimated, let lhsContent), .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let rhsTransitionstyle, let rhsAnimated, let rhsContent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsContent, rhs: rhsContent, with: matcher), lhsContent, rhsContent, "content")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_showUpdateRequiredView__showAccountLink_showAccountLink(p0): return p0.intValue - case let .m_backToRoot__animated_animated(p0): return p0.intValue - case let .m_back__animated_animated(p0): return p0.intValue - case .m_backWithFade: return 0 - case let .m_dismiss__animated_animated(p0): return p0.intValue - case let .m_removeLastView__controllers_controllers(p0): return p0.intValue - case let .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(p0, p1): return p0.intValue + p1.intValue - case .m_showStartupScreen: return 0 - case let .m_showLoginScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case let .m_showRegisterScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case .m_showForgotPasswordScreen: return 0 - case let .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(p0, p1): return p0.intValue + p1.intValue - case let .m_showWebBrowser__title_titleurl_url(p0, p1): return p0.intValue + p1.intValue - case let .m_showSSOWebBrowser__title_title(p0): return p0.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(p0, p1, p2, p3, p4, p5, p6, p7): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue + p7.intValue - case let .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_showUpdateRequiredView__showAccountLink_showAccountLink: return ".showUpdateRequiredView(showAccountLink:)" - case .m_backToRoot__animated_animated: return ".backToRoot(animated:)" - case .m_back__animated_animated: return ".back(animated:)" - case .m_backWithFade: return ".backWithFade()" - case .m_dismiss__animated_animated: return ".dismiss(animated:)" - case .m_removeLastView__controllers_controllers: return ".removeLastView(controllers:)" - case .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData: return ".showMainOrWhatsNewScreen(sourceScreen:postLoginData:)" - case .m_showStartupScreen: return ".showStartupScreen()" - case .m_showLoginScreen__sourceScreen_sourceScreen: return ".showLoginScreen(sourceScreen:)" - case .m_showRegisterScreen__sourceScreen_sourceScreen: return ".showRegisterScreen(sourceScreen:)" - case .m_showForgotPasswordScreen: return ".showForgotPasswordScreen()" - case .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen: return ".showDiscoveryScreen(searchQuery:sourceScreen:)" - case .m_showWebBrowser__title_titleurl_url: return ".showWebBrowser(title:url:)" - case .m_showSSOWebBrowser__title_title: return ".showSSOWebBrowser(title:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type: return ".presentAlert(alertTitle:alertMessage:positiveAction:onCloseTapped:firstButtonTapped:type:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped: return ".presentAlert(alertTitle:alertMessage:nextSectionName:action:image:onCloseTapped:firstButtonTapped:nextSectionTapped:)" - case .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion: return ".presentView(transitionStyle:view:completion:)" - case .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content: return ".presentView(transitionStyle:animated:content:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func showUpdateRequiredView(showAccountLink: Parameter) -> Verify { return Verify(method: .m_showUpdateRequiredView__showAccountLink_showAccountLink(`showAccountLink`))} - public static func backToRoot(animated: Parameter) -> Verify { return Verify(method: .m_backToRoot__animated_animated(`animated`))} - public static func back(animated: Parameter) -> Verify { return Verify(method: .m_back__animated_animated(`animated`))} - public static func backWithFade() -> Verify { return Verify(method: .m_backWithFade)} - public static func dismiss(animated: Parameter) -> Verify { return Verify(method: .m_dismiss__animated_animated(`animated`))} - public static func removeLastView(controllers: Parameter) -> Verify { return Verify(method: .m_removeLastView__controllers_controllers(`controllers`))} - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter) -> Verify { return Verify(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`))} - public static func showStartupScreen() -> Verify { return Verify(method: .m_showStartupScreen)} - public static func showLoginScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showRegisterScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showForgotPasswordScreen() -> Verify { return Verify(method: .m_showForgotPasswordScreen)} - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter) -> Verify { return Verify(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`))} - public static func showWebBrowser(title: Parameter, url: Parameter) -> Verify { return Verify(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`))} - public static func showSSOWebBrowser(title: Parameter) -> Verify { return Verify(method: .m_showSSOWebBrowser__title_title(`title`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`))} - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`))} - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func showUpdateRequiredView(showAccountLink: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_showUpdateRequiredView__showAccountLink_showAccountLink(`showAccountLink`), performs: perform) - } - public static func backToRoot(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_backToRoot__animated_animated(`animated`), performs: perform) - } - public static func back(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_back__animated_animated(`animated`), performs: perform) - } - public static func backWithFade(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_backWithFade, performs: perform) - } - public static func dismiss(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_dismiss__animated_animated(`animated`), performs: perform) - } - public static func removeLastView(controllers: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_removeLastView__controllers_controllers(`controllers`), performs: perform) - } - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter, perform: @escaping (LogistrationSourceScreen, PostLoginData?) -> Void) -> Perform { - return Perform(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`), performs: perform) - } - public static func showStartupScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showStartupScreen, performs: perform) - } - public static func showLoginScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showRegisterScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showForgotPasswordScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showForgotPasswordScreen, performs: perform) - } - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter, perform: @escaping (String?, LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`), performs: perform) - } - public static func showWebBrowser(title: Parameter, url: Parameter, perform: @escaping (String, URL) -> Void) -> Perform { - return Perform(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`), performs: perform) - } - public static func showSSOWebBrowser(title: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showSSOWebBrowser__title_title(`title`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter, perform: @escaping (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>, perform: @escaping (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>, perform: @escaping (UIModalTransitionStyle, any View, (() -> Void)?) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>, perform: @escaping (UIModalTransitionStyle, Bool, () -> any View) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - BaseRouter -@MainActor -open class BaseRouterMock: BaseRouter, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func backToRoot(animated: Bool) { - addInvocation(.m_backToRoot__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_backToRoot__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func back(animated: Bool) { - addInvocation(.m_back__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_back__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func backWithFade() { - addInvocation(.m_backWithFade) - let perform = methodPerformValue(.m_backWithFade) as? () -> Void - perform?() - } - - open func dismiss(animated: Bool) { - addInvocation(.m_dismiss__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_dismiss__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func removeLastView(controllers: Int) { - addInvocation(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) - let perform = methodPerformValue(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) as? (Int) -> Void - perform?(`controllers`) - } - - open func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { - addInvocation(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) - let perform = methodPerformValue(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) as? (LogistrationSourceScreen, PostLoginData?) -> Void - perform?(`sourceScreen`, `postLoginData`) - } - - open func showStartupScreen() { - addInvocation(.m_showStartupScreen) - let perform = methodPerformValue(.m_showStartupScreen) as? () -> Void - perform?() - } - - open func showLoginScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showForgotPasswordScreen() { - addInvocation(.m_showForgotPasswordScreen) - let perform = methodPerformValue(.m_showForgotPasswordScreen) as? () -> Void - perform?() - } - - open func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) as? (String?, LogistrationSourceScreen) -> Void - perform?(`searchQuery`, `sourceScreen`) - } - - open func showWebBrowser(title: String, url: URL) { - addInvocation(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) - let perform = methodPerformValue(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) as? (String, URL) -> Void - perform?(`title`, `url`) - } - - open func showSSOWebBrowser(title: String) { - addInvocation(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) - let perform = methodPerformValue(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) as? (String) -> Void - perform?(`title`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) as? (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void - perform?(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) as? (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void - perform?(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { - addInvocation(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) as? (UIModalTransitionStyle, any View, (() -> Void)?) -> Void - perform?(`transitionStyle`, `view`, `completion`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { - addInvocation(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) as? (UIModalTransitionStyle, Bool, () -> any View) -> Void - perform?(`transitionStyle`, `animated`, `content`) - } - - - fileprivate enum MethodType { - case m_backToRoot__animated_animated(Parameter) - case m_back__animated_animated(Parameter) - case m_backWithFade - case m_dismiss__animated_animated(Parameter) - case m_removeLastView__controllers_controllers(Parameter) - case m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter, Parameter) - case m_showStartupScreen - case m_showLoginScreen__sourceScreen_sourceScreen(Parameter) - case m_showRegisterScreen__sourceScreen_sourceScreen(Parameter) - case m_showForgotPasswordScreen - case m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter, Parameter) - case m_showWebBrowser__title_titleurl_url(Parameter, Parameter) - case m_showSSOWebBrowser__title_title(Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter<() -> Void>) - case m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter, Parameter, Parameter<(() -> Void)?>) - case m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter, Parameter, Parameter<() -> any View>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_backToRoot__animated_animated(let lhsAnimated), .m_backToRoot__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_back__animated_animated(let lhsAnimated), .m_back__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_backWithFade, .m_backWithFade): return .match - - case (.m_dismiss__animated_animated(let lhsAnimated), .m_dismiss__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_removeLastView__controllers_controllers(let lhsControllers), .m_removeLastView__controllers_controllers(let rhsControllers)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsControllers, rhs: rhsControllers, with: matcher), lhsControllers, rhsControllers, "controllers")) - return Matcher.ComparisonResult(results) - - case (.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let lhsSourcescreen, let lhsPostlogindata), .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let rhsSourcescreen, let rhsPostlogindata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPostlogindata, rhs: rhsPostlogindata, with: matcher), lhsPostlogindata, rhsPostlogindata, "postLoginData")) - return Matcher.ComparisonResult(results) - - case (.m_showStartupScreen, .m_showStartupScreen): return .match - - case (.m_showLoginScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showLoginScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showRegisterScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showRegisterScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showForgotPasswordScreen, .m_showForgotPasswordScreen): return .match - - case (.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let lhsSearchquery, let lhsSourcescreen), .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let rhsSearchquery, let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchquery, rhs: rhsSearchquery, with: matcher), lhsSearchquery, rhsSearchquery, "searchQuery")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showWebBrowser__title_titleurl_url(let lhsTitle, let lhsUrl), .m_showWebBrowser__title_titleurl_url(let rhsTitle, let rhsUrl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - return Matcher.ComparisonResult(results) - - case (.m_showSSOWebBrowser__title_title(let lhsTitle), .m_showSSOWebBrowser__title_title(let rhsTitle)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let lhsAlerttitle, let lhsAlertmessage, let lhsPositiveaction, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsType), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let rhsAlerttitle, let rhsAlertmessage, let rhsPositiveaction, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPositiveaction, rhs: rhsPositiveaction, with: matcher), lhsPositiveaction, rhsPositiveaction, "positiveAction")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let lhsAlerttitle, let lhsAlertmessage, let lhsNextsectionname, let lhsAction, let lhsImage, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsNextsectiontapped), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let rhsAlerttitle, let rhsAlertmessage, let rhsNextsectionname, let rhsAction, let rhsImage, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsNextsectiontapped)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectionname, rhs: rhsNextsectionname, with: matcher), lhsNextsectionname, rhsNextsectionname, "nextSectionName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsImage, rhs: rhsImage, with: matcher), lhsImage, rhsImage, "image")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectiontapped, rhs: rhsNextsectiontapped, with: matcher), lhsNextsectiontapped, rhsNextsectiontapped, "nextSectionTapped")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let lhsTransitionstyle, let lhsView, let lhsCompletion), .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let rhsTransitionstyle, let rhsView, let rhsCompletion)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsView, rhs: rhsView, with: matcher), lhsView, rhsView, "view")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCompletion, rhs: rhsCompletion, with: matcher), lhsCompletion, rhsCompletion, "completion")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let lhsTransitionstyle, let lhsAnimated, let lhsContent), .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let rhsTransitionstyle, let rhsAnimated, let rhsContent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsContent, rhs: rhsContent, with: matcher), lhsContent, rhsContent, "content")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_backToRoot__animated_animated(p0): return p0.intValue - case let .m_back__animated_animated(p0): return p0.intValue - case .m_backWithFade: return 0 - case let .m_dismiss__animated_animated(p0): return p0.intValue - case let .m_removeLastView__controllers_controllers(p0): return p0.intValue - case let .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(p0, p1): return p0.intValue + p1.intValue - case .m_showStartupScreen: return 0 - case let .m_showLoginScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case let .m_showRegisterScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case .m_showForgotPasswordScreen: return 0 - case let .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(p0, p1): return p0.intValue + p1.intValue - case let .m_showWebBrowser__title_titleurl_url(p0, p1): return p0.intValue + p1.intValue - case let .m_showSSOWebBrowser__title_title(p0): return p0.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(p0, p1, p2, p3, p4, p5, p6, p7): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue + p7.intValue - case let .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_backToRoot__animated_animated: return ".backToRoot(animated:)" - case .m_back__animated_animated: return ".back(animated:)" - case .m_backWithFade: return ".backWithFade()" - case .m_dismiss__animated_animated: return ".dismiss(animated:)" - case .m_removeLastView__controllers_controllers: return ".removeLastView(controllers:)" - case .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData: return ".showMainOrWhatsNewScreen(sourceScreen:postLoginData:)" - case .m_showStartupScreen: return ".showStartupScreen()" - case .m_showLoginScreen__sourceScreen_sourceScreen: return ".showLoginScreen(sourceScreen:)" - case .m_showRegisterScreen__sourceScreen_sourceScreen: return ".showRegisterScreen(sourceScreen:)" - case .m_showForgotPasswordScreen: return ".showForgotPasswordScreen()" - case .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen: return ".showDiscoveryScreen(searchQuery:sourceScreen:)" - case .m_showWebBrowser__title_titleurl_url: return ".showWebBrowser(title:url:)" - case .m_showSSOWebBrowser__title_title: return ".showSSOWebBrowser(title:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type: return ".presentAlert(alertTitle:alertMessage:positiveAction:onCloseTapped:firstButtonTapped:type:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped: return ".presentAlert(alertTitle:alertMessage:nextSectionName:action:image:onCloseTapped:firstButtonTapped:nextSectionTapped:)" - case .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion: return ".presentView(transitionStyle:view:completion:)" - case .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content: return ".presentView(transitionStyle:animated:content:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func backToRoot(animated: Parameter) -> Verify { return Verify(method: .m_backToRoot__animated_animated(`animated`))} - public static func back(animated: Parameter) -> Verify { return Verify(method: .m_back__animated_animated(`animated`))} - public static func backWithFade() -> Verify { return Verify(method: .m_backWithFade)} - public static func dismiss(animated: Parameter) -> Verify { return Verify(method: .m_dismiss__animated_animated(`animated`))} - public static func removeLastView(controllers: Parameter) -> Verify { return Verify(method: .m_removeLastView__controllers_controllers(`controllers`))} - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter) -> Verify { return Verify(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`))} - public static func showStartupScreen() -> Verify { return Verify(method: .m_showStartupScreen)} - public static func showLoginScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showRegisterScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showForgotPasswordScreen() -> Verify { return Verify(method: .m_showForgotPasswordScreen)} - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter) -> Verify { return Verify(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`))} - public static func showWebBrowser(title: Parameter, url: Parameter) -> Verify { return Verify(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`))} - public static func showSSOWebBrowser(title: Parameter) -> Verify { return Verify(method: .m_showSSOWebBrowser__title_title(`title`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`))} - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`))} - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func backToRoot(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_backToRoot__animated_animated(`animated`), performs: perform) - } - public static func back(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_back__animated_animated(`animated`), performs: perform) - } - public static func backWithFade(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_backWithFade, performs: perform) - } - public static func dismiss(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_dismiss__animated_animated(`animated`), performs: perform) - } - public static func removeLastView(controllers: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_removeLastView__controllers_controllers(`controllers`), performs: perform) - } - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter, perform: @escaping (LogistrationSourceScreen, PostLoginData?) -> Void) -> Perform { - return Perform(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`), performs: perform) - } - public static func showStartupScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showStartupScreen, performs: perform) - } - public static func showLoginScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showRegisterScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showForgotPasswordScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showForgotPasswordScreen, performs: perform) - } - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter, perform: @escaping (String?, LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`), performs: perform) - } - public static func showWebBrowser(title: Parameter, url: Parameter, perform: @escaping (String, URL) -> Void) -> Perform { - return Perform(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`), performs: perform) - } - public static func showSSOWebBrowser(title: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showSSOWebBrowser__title_title(`title`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter, perform: @escaping (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>, perform: @escaping (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>, perform: @escaping (UIModalTransitionStyle, any View, (() -> Void)?) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>, perform: @escaping (UIModalTransitionStyle, Bool, () -> any View) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CalendarManagerProtocol -@MainActor -open class CalendarManagerProtocolMock: CalendarManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func createCalendarIfNeeded() { - addInvocation(.m_createCalendarIfNeeded) - let perform = methodPerformValue(.m_createCalendarIfNeeded) as? () -> Void - perform?() - } - - open func filterCoursesBySelected(fetchedCourses: [CourseForSync]) -> [CourseForSync] { - addInvocation(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) - let perform = methodPerformValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) as? ([CourseForSync]) -> Void - perform?(`fetchedCourses`) - var __value: [CourseForSync] - do { - __value = try methodReturnValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))).casted() - } catch { - onFatalFailure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - Failure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - } - return __value - } - - open func removeOldCalendar() { - addInvocation(.m_removeOldCalendar) - let perform = methodPerformValue(.m_removeOldCalendar) as? () -> Void - perform?() - } - - open func removeOutdatedEvents(courseID: String) { - addInvocation(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - } - - open func syncCourse(courseID: String, courseName: String, dates: CourseDates) { - addInvocation(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) - let perform = methodPerformValue(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) as? (String, String, CourseDates) -> Void - perform?(`courseID`, `courseName`, `dates`) - } - - open func requestAccess() -> Bool { - addInvocation(.m_requestAccess) - let perform = methodPerformValue(.m_requestAccess) as? () -> Void - perform?() - var __value: Bool - do { - __value = try methodReturnValue(.m_requestAccess).casted() - } catch { - onFatalFailure("Stub return value not specified for requestAccess(). Use given") - Failure("Stub return value not specified for requestAccess(). Use given") - } - return __value - } - - open func courseStatus(courseID: String) -> SyncStatus { - addInvocation(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: SyncStatus - do { - __value = try methodReturnValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for courseStatus(courseID: String). Use given") - Failure("Stub return value not specified for courseStatus(courseID: String). Use given") - } - return __value - } - - open func clearAllData(removeCalendar: Bool) { - addInvocation(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) - let perform = methodPerformValue(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) as? (Bool) -> Void - perform?(`removeCalendar`) - } - - open func isDatesChanged(courseID: String, checksum: String) -> Bool { - addInvocation(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) - let perform = methodPerformValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) as? (String, String) -> Void - perform?(`courseID`, `checksum`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - Failure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - } - return __value - } - - - fileprivate enum MethodType { - case m_createCalendarIfNeeded - case m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>) - case m_removeOldCalendar - case m_removeOutdatedEvents__courseID_courseID(Parameter) - case m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter, Parameter, Parameter) - case m_requestAccess - case m_courseStatus__courseID_courseID(Parameter) - case m_clearAllData__removeCalendar_removeCalendar(Parameter) - case m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_createCalendarIfNeeded, .m_createCalendarIfNeeded): return .match - - case (.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let lhsFetchedcourses), .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let rhsFetchedcourses)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFetchedcourses, rhs: rhsFetchedcourses, with: matcher), lhsFetchedcourses, rhsFetchedcourses, "fetchedCourses")) - return Matcher.ComparisonResult(results) - - case (.m_removeOldCalendar, .m_removeOldCalendar): return .match - - case (.m_removeOutdatedEvents__courseID_courseID(let lhsCourseid), .m_removeOutdatedEvents__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let lhsCourseid, let lhsCoursename, let lhsDates), .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let rhsCourseid, let rhsCoursename, let rhsDates)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDates, rhs: rhsDates, with: matcher), lhsDates, rhsDates, "dates")) - return Matcher.ComparisonResult(results) - - case (.m_requestAccess, .m_requestAccess): return .match - - case (.m_courseStatus__courseID_courseID(let lhsCourseid), .m_courseStatus__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_clearAllData__removeCalendar_removeCalendar(let lhsRemovecalendar), .m_clearAllData__removeCalendar_removeCalendar(let rhsRemovecalendar)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRemovecalendar, rhs: rhsRemovecalendar, with: matcher), lhsRemovecalendar, rhsRemovecalendar, "removeCalendar")) - return Matcher.ComparisonResult(results) - - case (.m_isDatesChanged__courseID_courseIDchecksum_checksum(let lhsCourseid, let lhsChecksum), .m_isDatesChanged__courseID_courseIDchecksum_checksum(let rhsCourseid, let rhsChecksum)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsChecksum, rhs: rhsChecksum, with: matcher), lhsChecksum, rhsChecksum, "checksum")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_createCalendarIfNeeded: return 0 - case let .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(p0): return p0.intValue - case .m_removeOldCalendar: return 0 - case let .m_removeOutdatedEvents__courseID_courseID(p0): return p0.intValue - case let .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case .m_requestAccess: return 0 - case let .m_courseStatus__courseID_courseID(p0): return p0.intValue - case let .m_clearAllData__removeCalendar_removeCalendar(p0): return p0.intValue - case let .m_isDatesChanged__courseID_courseIDchecksum_checksum(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_createCalendarIfNeeded: return ".createCalendarIfNeeded()" - case .m_filterCoursesBySelected__fetchedCourses_fetchedCourses: return ".filterCoursesBySelected(fetchedCourses:)" - case .m_removeOldCalendar: return ".removeOldCalendar()" - case .m_removeOutdatedEvents__courseID_courseID: return ".removeOutdatedEvents(courseID:)" - case .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates: return ".syncCourse(courseID:courseName:dates:)" - case .m_requestAccess: return ".requestAccess()" - case .m_courseStatus__courseID_courseID: return ".courseStatus(courseID:)" - case .m_clearAllData__removeCalendar_removeCalendar: return ".clearAllData(removeCalendar:)" - case .m_isDatesChanged__courseID_courseIDchecksum_checksum: return ".isDatesChanged(courseID:checksum:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willReturn: [CourseForSync]...) -> MethodStub { - return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func requestAccess(willReturn: Bool...) -> MethodStub { - return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func courseStatus(courseID: Parameter, willReturn: SyncStatus...) -> MethodStub { - return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willProduce: (Stubber<[CourseForSync]>) -> Void) -> MethodStub { - let willReturn: [[CourseForSync]] = [] - let given: Given = { return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([CourseForSync]).self) - willProduce(stubber) - return given - } - public static func requestAccess(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func courseStatus(courseID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [SyncStatus] = [] - let given: Given = { return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (SyncStatus).self) - willProduce(stubber) - return given - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func createCalendarIfNeeded() -> Verify { return Verify(method: .m_createCalendarIfNeeded)} - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>) -> Verify { return Verify(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`))} - public static func removeOldCalendar() -> Verify { return Verify(method: .m_removeOldCalendar)} - public static func removeOutdatedEvents(courseID: Parameter) -> Verify { return Verify(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`))} - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter) -> Verify { return Verify(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`))} - public static func requestAccess() -> Verify { return Verify(method: .m_requestAccess)} - public static func courseStatus(courseID: Parameter) -> Verify { return Verify(method: .m_courseStatus__courseID_courseID(`courseID`))} - public static func clearAllData(removeCalendar: Parameter) -> Verify { return Verify(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`))} - public static func isDatesChanged(courseID: Parameter, checksum: Parameter) -> Verify { return Verify(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func createCalendarIfNeeded(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_createCalendarIfNeeded, performs: perform) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, perform: @escaping ([CourseForSync]) -> Void) -> Perform { - return Perform(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), performs: perform) - } - public static func removeOldCalendar(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeOldCalendar, performs: perform) - } - public static func removeOutdatedEvents(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`), performs: perform) - } - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter, perform: @escaping (String, String, CourseDates) -> Void) -> Perform { - return Perform(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`), performs: perform) - } - public static func requestAccess(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_requestAccess, performs: perform) - } - public static func courseStatus(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_courseStatus__courseID_courseID(`courseID`), performs: perform) - } - public static func clearAllData(removeCalendar: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`), performs: perform) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConfigProtocol - -open class ConfigProtocolMock: ConfigProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var baseURL: URL { - get { invocations.append(.p_baseURL_get); return __p_baseURL ?? givenGetterValue(.p_baseURL_get, "ConfigProtocolMock - stub value for baseURL was not defined") } - } - private var __p_baseURL: (URL)? - - public var baseSSOURL: URL { - get { invocations.append(.p_baseSSOURL_get); return __p_baseSSOURL ?? givenGetterValue(.p_baseSSOURL_get, "ConfigProtocolMock - stub value for baseSSOURL was not defined") } - } - private var __p_baseSSOURL: (URL)? - - public var ssoFinishedURL: URL { - get { invocations.append(.p_ssoFinishedURL_get); return __p_ssoFinishedURL ?? givenGetterValue(.p_ssoFinishedURL_get, "ConfigProtocolMock - stub value for ssoFinishedURL was not defined") } - } - private var __p_ssoFinishedURL: (URL)? - - public var ssoButtonTitle: [String: Any] { - get { invocations.append(.p_ssoButtonTitle_get); return __p_ssoButtonTitle ?? givenGetterValue(.p_ssoButtonTitle_get, "ConfigProtocolMock - stub value for ssoButtonTitle was not defined") } - } - private var __p_ssoButtonTitle: ([String: Any])? - - public var oAuthClientId: String { - get { invocations.append(.p_oAuthClientId_get); return __p_oAuthClientId ?? givenGetterValue(.p_oAuthClientId_get, "ConfigProtocolMock - stub value for oAuthClientId was not defined") } - } - private var __p_oAuthClientId: (String)? - - public var tokenType: TokenType { - get { invocations.append(.p_tokenType_get); return __p_tokenType ?? givenGetterValue(.p_tokenType_get, "ConfigProtocolMock - stub value for tokenType was not defined") } - } - private var __p_tokenType: (TokenType)? - - public var feedbackEmail: String { - get { invocations.append(.p_feedbackEmail_get); return __p_feedbackEmail ?? givenGetterValue(.p_feedbackEmail_get, "ConfigProtocolMock - stub value for feedbackEmail was not defined") } - } - private var __p_feedbackEmail: (String)? - - public var appStoreLink: String { - get { invocations.append(.p_appStoreLink_get); return __p_appStoreLink ?? givenGetterValue(.p_appStoreLink_get, "ConfigProtocolMock - stub value for appStoreLink was not defined") } - } - private var __p_appStoreLink: (String)? - - public var faq: URL? { - get { invocations.append(.p_faq_get); return __p_faq ?? optionalGivenGetterValue(.p_faq_get, "ConfigProtocolMock - stub value for faq was not defined") } - } - private var __p_faq: (URL)? - - public var platformName: String { - get { invocations.append(.p_platformName_get); return __p_platformName ?? givenGetterValue(.p_platformName_get, "ConfigProtocolMock - stub value for platformName was not defined") } - } - private var __p_platformName: (String)? - - public var agreement: AgreementConfig { - get { invocations.append(.p_agreement_get); return __p_agreement ?? givenGetterValue(.p_agreement_get, "ConfigProtocolMock - stub value for agreement was not defined") } - } - private var __p_agreement: (AgreementConfig)? - - public var firebase: FirebaseConfig { - get { invocations.append(.p_firebase_get); return __p_firebase ?? givenGetterValue(.p_firebase_get, "ConfigProtocolMock - stub value for firebase was not defined") } - } - private var __p_firebase: (FirebaseConfig)? - - public var facebook: FacebookConfig { - get { invocations.append(.p_facebook_get); return __p_facebook ?? givenGetterValue(.p_facebook_get, "ConfigProtocolMock - stub value for facebook was not defined") } - } - private var __p_facebook: (FacebookConfig)? - - public var microsoft: MicrosoftConfig { - get { invocations.append(.p_microsoft_get); return __p_microsoft ?? givenGetterValue(.p_microsoft_get, "ConfigProtocolMock - stub value for microsoft was not defined") } - } - private var __p_microsoft: (MicrosoftConfig)? - - public var google: GoogleConfig { - get { invocations.append(.p_google_get); return __p_google ?? givenGetterValue(.p_google_get, "ConfigProtocolMock - stub value for google was not defined") } - } - private var __p_google: (GoogleConfig)? - - public var appleSignIn: AppleSignInConfig { - get { invocations.append(.p_appleSignIn_get); return __p_appleSignIn ?? givenGetterValue(.p_appleSignIn_get, "ConfigProtocolMock - stub value for appleSignIn was not defined") } - } - private var __p_appleSignIn: (AppleSignInConfig)? - - public var features: FeaturesConfig { - get { invocations.append(.p_features_get); return __p_features ?? givenGetterValue(.p_features_get, "ConfigProtocolMock - stub value for features was not defined") } - } - private var __p_features: (FeaturesConfig)? - - public var theme: ThemeConfig { - get { invocations.append(.p_theme_get); return __p_theme ?? givenGetterValue(.p_theme_get, "ConfigProtocolMock - stub value for theme was not defined") } - } - private var __p_theme: (ThemeConfig)? - - public var uiComponents: UIComponentsConfig { - get { invocations.append(.p_uiComponents_get); return __p_uiComponents ?? givenGetterValue(.p_uiComponents_get, "ConfigProtocolMock - stub value for uiComponents was not defined") } - } - private var __p_uiComponents: (UIComponentsConfig)? - - public var discovery: DiscoveryConfig { - get { invocations.append(.p_discovery_get); return __p_discovery ?? givenGetterValue(.p_discovery_get, "ConfigProtocolMock - stub value for discovery was not defined") } - } - private var __p_discovery: (DiscoveryConfig)? - - public var dashboard: DashboardConfig { - get { invocations.append(.p_dashboard_get); return __p_dashboard ?? givenGetterValue(.p_dashboard_get, "ConfigProtocolMock - stub value for dashboard was not defined") } - } - private var __p_dashboard: (DashboardConfig)? - - public var braze: BrazeConfig { - get { invocations.append(.p_braze_get); return __p_braze ?? givenGetterValue(.p_braze_get, "ConfigProtocolMock - stub value for braze was not defined") } - } - private var __p_braze: (BrazeConfig)? - - public var branch: BranchConfig { - get { invocations.append(.p_branch_get); return __p_branch ?? givenGetterValue(.p_branch_get, "ConfigProtocolMock - stub value for branch was not defined") } - } - private var __p_branch: (BranchConfig)? - - public var program: DiscoveryConfig { - get { invocations.append(.p_program_get); return __p_program ?? givenGetterValue(.p_program_get, "ConfigProtocolMock - stub value for program was not defined") } - } - private var __p_program: (DiscoveryConfig)? - - public var experimentalFeatures: ExperimentalFeaturesConfig { - get { invocations.append(.p_experimentalFeatures_get); return __p_experimentalFeatures ?? givenGetterValue(.p_experimentalFeatures_get, "ConfigProtocolMock - stub value for experimentalFeatures was not defined") } - } - private var __p_experimentalFeatures: (ExperimentalFeaturesConfig)? - - public var URIScheme: String { - get { invocations.append(.p_URIScheme_get); return __p_URIScheme ?? givenGetterValue(.p_URIScheme_get, "ConfigProtocolMock - stub value for URIScheme was not defined") } - } - private var __p_URIScheme: (String)? - - - - - - - fileprivate enum MethodType { - case p_baseURL_get - case p_baseSSOURL_get - case p_ssoFinishedURL_get - case p_ssoButtonTitle_get - case p_oAuthClientId_get - case p_tokenType_get - case p_feedbackEmail_get - case p_appStoreLink_get - case p_faq_get - case p_platformName_get - case p_agreement_get - case p_firebase_get - case p_facebook_get - case p_microsoft_get - case p_google_get - case p_appleSignIn_get - case p_features_get - case p_theme_get - case p_uiComponents_get - case p_discovery_get - case p_dashboard_get - case p_braze_get - case p_branch_get - case p_program_get - case p_experimentalFeatures_get - case p_URIScheme_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_baseURL_get,.p_baseURL_get): return Matcher.ComparisonResult.match - case (.p_baseSSOURL_get,.p_baseSSOURL_get): return Matcher.ComparisonResult.match - case (.p_ssoFinishedURL_get,.p_ssoFinishedURL_get): return Matcher.ComparisonResult.match - case (.p_ssoButtonTitle_get,.p_ssoButtonTitle_get): return Matcher.ComparisonResult.match - case (.p_oAuthClientId_get,.p_oAuthClientId_get): return Matcher.ComparisonResult.match - case (.p_tokenType_get,.p_tokenType_get): return Matcher.ComparisonResult.match - case (.p_feedbackEmail_get,.p_feedbackEmail_get): return Matcher.ComparisonResult.match - case (.p_appStoreLink_get,.p_appStoreLink_get): return Matcher.ComparisonResult.match - case (.p_faq_get,.p_faq_get): return Matcher.ComparisonResult.match - case (.p_platformName_get,.p_platformName_get): return Matcher.ComparisonResult.match - case (.p_agreement_get,.p_agreement_get): return Matcher.ComparisonResult.match - case (.p_firebase_get,.p_firebase_get): return Matcher.ComparisonResult.match - case (.p_facebook_get,.p_facebook_get): return Matcher.ComparisonResult.match - case (.p_microsoft_get,.p_microsoft_get): return Matcher.ComparisonResult.match - case (.p_google_get,.p_google_get): return Matcher.ComparisonResult.match - case (.p_appleSignIn_get,.p_appleSignIn_get): return Matcher.ComparisonResult.match - case (.p_features_get,.p_features_get): return Matcher.ComparisonResult.match - case (.p_theme_get,.p_theme_get): return Matcher.ComparisonResult.match - case (.p_uiComponents_get,.p_uiComponents_get): return Matcher.ComparisonResult.match - case (.p_discovery_get,.p_discovery_get): return Matcher.ComparisonResult.match - case (.p_dashboard_get,.p_dashboard_get): return Matcher.ComparisonResult.match - case (.p_braze_get,.p_braze_get): return Matcher.ComparisonResult.match - case (.p_branch_get,.p_branch_get): return Matcher.ComparisonResult.match - case (.p_program_get,.p_program_get): return Matcher.ComparisonResult.match - case (.p_experimentalFeatures_get,.p_experimentalFeatures_get): return Matcher.ComparisonResult.match - case (.p_URIScheme_get,.p_URIScheme_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_baseURL_get: return 0 - case .p_baseSSOURL_get: return 0 - case .p_ssoFinishedURL_get: return 0 - case .p_ssoButtonTitle_get: return 0 - case .p_oAuthClientId_get: return 0 - case .p_tokenType_get: return 0 - case .p_feedbackEmail_get: return 0 - case .p_appStoreLink_get: return 0 - case .p_faq_get: return 0 - case .p_platformName_get: return 0 - case .p_agreement_get: return 0 - case .p_firebase_get: return 0 - case .p_facebook_get: return 0 - case .p_microsoft_get: return 0 - case .p_google_get: return 0 - case .p_appleSignIn_get: return 0 - case .p_features_get: return 0 - case .p_theme_get: return 0 - case .p_uiComponents_get: return 0 - case .p_discovery_get: return 0 - case .p_dashboard_get: return 0 - case .p_braze_get: return 0 - case .p_branch_get: return 0 - case .p_program_get: return 0 - case .p_experimentalFeatures_get: return 0 - case .p_URIScheme_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_baseURL_get: return "[get] .baseURL" - case .p_baseSSOURL_get: return "[get] .baseSSOURL" - case .p_ssoFinishedURL_get: return "[get] .ssoFinishedURL" - case .p_ssoButtonTitle_get: return "[get] .ssoButtonTitle" - case .p_oAuthClientId_get: return "[get] .oAuthClientId" - case .p_tokenType_get: return "[get] .tokenType" - case .p_feedbackEmail_get: return "[get] .feedbackEmail" - case .p_appStoreLink_get: return "[get] .appStoreLink" - case .p_faq_get: return "[get] .faq" - case .p_platformName_get: return "[get] .platformName" - case .p_agreement_get: return "[get] .agreement" - case .p_firebase_get: return "[get] .firebase" - case .p_facebook_get: return "[get] .facebook" - case .p_microsoft_get: return "[get] .microsoft" - case .p_google_get: return "[get] .google" - case .p_appleSignIn_get: return "[get] .appleSignIn" - case .p_features_get: return "[get] .features" - case .p_theme_get: return "[get] .theme" - case .p_uiComponents_get: return "[get] .uiComponents" - case .p_discovery_get: return "[get] .discovery" - case .p_dashboard_get: return "[get] .dashboard" - case .p_braze_get: return "[get] .braze" - case .p_branch_get: return "[get] .branch" - case .p_program_get: return "[get] .program" - case .p_experimentalFeatures_get: return "[get] .experimentalFeatures" - case .p_URIScheme_get: return "[get] .URIScheme" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func baseURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func baseSSOURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseSSOURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoFinishedURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_ssoFinishedURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoButtonTitle(getter defaultValue: [String: Any]...) -> PropertyStub { - return Given(method: .p_ssoButtonTitle_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func oAuthClientId(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_oAuthClientId_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func tokenType(getter defaultValue: TokenType...) -> PropertyStub { - return Given(method: .p_tokenType_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func feedbackEmail(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_feedbackEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appStoreLink(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_appStoreLink_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func faq(getter defaultValue: URL?...) -> PropertyStub { - return Given(method: .p_faq_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func platformName(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_platformName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func agreement(getter defaultValue: AgreementConfig...) -> PropertyStub { - return Given(method: .p_agreement_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func firebase(getter defaultValue: FirebaseConfig...) -> PropertyStub { - return Given(method: .p_firebase_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func facebook(getter defaultValue: FacebookConfig...) -> PropertyStub { - return Given(method: .p_facebook_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func microsoft(getter defaultValue: MicrosoftConfig...) -> PropertyStub { - return Given(method: .p_microsoft_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func google(getter defaultValue: GoogleConfig...) -> PropertyStub { - return Given(method: .p_google_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignIn(getter defaultValue: AppleSignInConfig...) -> PropertyStub { - return Given(method: .p_appleSignIn_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func features(getter defaultValue: FeaturesConfig...) -> PropertyStub { - return Given(method: .p_features_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func theme(getter defaultValue: ThemeConfig...) -> PropertyStub { - return Given(method: .p_theme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func uiComponents(getter defaultValue: UIComponentsConfig...) -> PropertyStub { - return Given(method: .p_uiComponents_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func discovery(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_discovery_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func dashboard(getter defaultValue: DashboardConfig...) -> PropertyStub { - return Given(method: .p_dashboard_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func braze(getter defaultValue: BrazeConfig...) -> PropertyStub { - return Given(method: .p_braze_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func branch(getter defaultValue: BranchConfig...) -> PropertyStub { - return Given(method: .p_branch_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func program(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_program_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func experimentalFeatures(getter defaultValue: ExperimentalFeaturesConfig...) -> PropertyStub { - return Given(method: .p_experimentalFeatures_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func URIScheme(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_URIScheme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var baseURL: Verify { return Verify(method: .p_baseURL_get) } - public static var baseSSOURL: Verify { return Verify(method: .p_baseSSOURL_get) } - public static var ssoFinishedURL: Verify { return Verify(method: .p_ssoFinishedURL_get) } - public static var ssoButtonTitle: Verify { return Verify(method: .p_ssoButtonTitle_get) } - public static var oAuthClientId: Verify { return Verify(method: .p_oAuthClientId_get) } - public static var tokenType: Verify { return Verify(method: .p_tokenType_get) } - public static var feedbackEmail: Verify { return Verify(method: .p_feedbackEmail_get) } - public static var appStoreLink: Verify { return Verify(method: .p_appStoreLink_get) } - public static var faq: Verify { return Verify(method: .p_faq_get) } - public static var platformName: Verify { return Verify(method: .p_platformName_get) } - public static var agreement: Verify { return Verify(method: .p_agreement_get) } - public static var firebase: Verify { return Verify(method: .p_firebase_get) } - public static var facebook: Verify { return Verify(method: .p_facebook_get) } - public static var microsoft: Verify { return Verify(method: .p_microsoft_get) } - public static var google: Verify { return Verify(method: .p_google_get) } - public static var appleSignIn: Verify { return Verify(method: .p_appleSignIn_get) } - public static var features: Verify { return Verify(method: .p_features_get) } - public static var theme: Verify { return Verify(method: .p_theme_get) } - public static var uiComponents: Verify { return Verify(method: .p_uiComponents_get) } - public static var discovery: Verify { return Verify(method: .p_discovery_get) } - public static var dashboard: Verify { return Verify(method: .p_dashboard_get) } - public static var braze: Verify { return Verify(method: .p_braze_get) } - public static var branch: Verify { return Verify(method: .p_branch_get) } - public static var program: Verify { return Verify(method: .p_program_get) } - public static var experimentalFeatures: Verify { return Verify(method: .p_experimentalFeatures_get) } - public static var URIScheme: Verify { return Verify(method: .p_URIScheme_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConnectivityProtocol -@MainActor -open class ConnectivityProtocolMock: ConnectivityProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var isInternetAvaliable: Bool { - get { invocations.append(.p_isInternetAvaliable_get); return __p_isInternetAvaliable ?? givenGetterValue(.p_isInternetAvaliable_get, "ConnectivityProtocolMock - stub value for isInternetAvaliable was not defined") } - } - private var __p_isInternetAvaliable: (Bool)? - - public var isMobileData: Bool { - get { invocations.append(.p_isMobileData_get); return __p_isMobileData ?? givenGetterValue(.p_isMobileData_get, "ConnectivityProtocolMock - stub value for isMobileData was not defined") } - } - private var __p_isMobileData: (Bool)? - - public var internetReachableSubject: CurrentValueSubject { - get { invocations.append(.p_internetReachableSubject_get); return __p_internetReachableSubject ?? givenGetterValue(.p_internetReachableSubject_get, "ConnectivityProtocolMock - stub value for internetReachableSubject was not defined") } - } - private var __p_internetReachableSubject: (CurrentValueSubject)? - - - - - - - fileprivate enum MethodType { - case p_isInternetAvaliable_get - case p_isMobileData_get - case p_internetReachableSubject_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_isInternetAvaliable_get,.p_isInternetAvaliable_get): return Matcher.ComparisonResult.match - case (.p_isMobileData_get,.p_isMobileData_get): return Matcher.ComparisonResult.match - case (.p_internetReachableSubject_get,.p_internetReachableSubject_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_isInternetAvaliable_get: return 0 - case .p_isMobileData_get: return 0 - case .p_internetReachableSubject_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_isInternetAvaliable_get: return "[get] .isInternetAvaliable" - case .p_isMobileData_get: return "[get] .isMobileData" - case .p_internetReachableSubject_get: return "[get] .internetReachableSubject" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func isInternetAvaliable(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isInternetAvaliable_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func isMobileData(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isMobileData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func internetReachableSubject(getter defaultValue: CurrentValueSubject...) -> PropertyStub { - return Given(method: .p_internetReachableSubject_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var isInternetAvaliable: Verify { return Verify(method: .p_isInternetAvaliable_get) } - public static var isMobileData: Verify { return Verify(method: .p_isMobileData_get) } - public static var internetReachableSubject: Verify { return Verify(method: .p_internetReachableSubject_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreAnalytics - -open class CoreAnalyticsMock: CoreAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { - addInvocation(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) - let perform = methodPerformValue(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) as? (AnalyticsEvent, EventBIValue, String?, Int?) -> Void - perform?(`event`, `biValue`, `action`, `rating`) - } - - open func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { - addInvocation(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) - let perform = methodPerformValue(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) as? (AnalyticsEvent, EventBIValue, String, String) -> Void - perform?(`event`, `bivalue`, `value`, `oldValue`) - } - - open func trackEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackScreenEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackScreenEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - - fileprivate enum MethodType { - case m_trackEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter, Parameter, Parameter, Parameter) - case m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter, Parameter, Parameter, Parameter) - case m_trackEvent__event(Parameter) - case m_trackEvent__eventbiValue_biValue(Parameter, Parameter) - case m_trackScreenEvent__event(Parameter) - case m_trackScreenEvent__eventbiValue_biValue(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_trackEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackScreenEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_appreview__eventbiValue_biValueaction_actionrating_rating(let lhsEvent, let lhsBivalue, let lhsAction, let lhsRating), .m_appreview__eventbiValue_biValueaction_actionrating_rating(let rhsEvent, let rhsBivalue, let rhsAction, let rhsRating)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRating, rhs: rhsRating, with: matcher), lhsRating, rhsRating, "rating")) - return Matcher.ComparisonResult(results) - - case (.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let lhsEvent, let lhsBivalue, let lhsValue, let lhsOldvalue), .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let rhsEvent, let rhsBivalue, let rhsValue, let rhsOldvalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "bivalue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsValue, rhs: rhsValue, with: matcher), lhsValue, rhsValue, "value")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOldvalue, rhs: rhsOldvalue, with: matcher), lhsOldvalue, rhsOldvalue, "oldValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__event(let lhsEvent), .m_trackEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__event(let lhsEvent), .m_trackScreenEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackScreenEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_trackEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_trackScreenEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_appreview__eventbiValue_biValueaction_actionrating_rating(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_trackEvent__event(p0): return p0.intValue - case let .m_trackEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__event(p0): return p0.intValue - case let .m_trackScreenEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_trackEvent__eventparameters_parameters: return ".trackEvent(_:parameters:)" - case .m_trackEvent__eventbiValue_biValueparameters_parameters: return ".trackEvent(_:biValue:parameters:)" - case .m_trackScreenEvent__eventparameters_parameters: return ".trackScreenEvent(_:parameters:)" - case .m_trackScreenEvent__eventbiValue_biValueparameters_parameters: return ".trackScreenEvent(_:biValue:parameters:)" - case .m_appreview__eventbiValue_biValueaction_actionrating_rating: return ".appreview(_:biValue:action:rating:)" - case .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue: return ".videoQualityChanged(_:bivalue:value:oldValue:)" - case .m_trackEvent__event: return ".trackEvent(_:)" - case .m_trackEvent__eventbiValue_biValue: return ".trackEvent(_:biValue:)" - case .m_trackScreenEvent__event: return ".trackScreenEvent(_:)" - case .m_trackScreenEvent__eventbiValue_biValue: return ".trackScreenEvent(_:biValue:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter) -> Verify { return Verify(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`))} - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter) -> Verify { return Verify(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`))} - public static func trackEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackEvent__event(`event`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`))} - public static func trackScreenEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__event(`event`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String?, Int?) -> Void) -> Perform { - return Perform(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`), performs: perform) - } - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String, String) -> Void) -> Perform { - return Perform(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`), performs: perform) - } - public static func trackEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackEvent__event(`event`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__event(`event`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CorePersistenceProtocol - -open class CorePersistenceProtocolMock: CorePersistenceProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func set(userId: Int) { - addInvocation(.m_set__userId_userId(Parameter.value(`userId`))) - let perform = methodPerformValue(.m_set__userId_userId(Parameter.value(`userId`))) as? (Int) -> Void - perform?(`userId`) - } - - open func getUserID() -> Int? { - addInvocation(.m_getUserID) - let perform = methodPerformValue(.m_getUserID) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getUserID).casted() - } catch { - // do nothing - } - return __value - } - - @MainActor - open func publisher() throws -> AnyPublisher { - addInvocation(.m_publisher) - let perform = methodPerformValue(.m_publisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_publisher).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for publisher(). Use given") - Failure("Stub return value not specified for publisher(). Use given") - } catch { - throw error - } - return __value - } - - open func addToDownloadQueue(tasks: [DownloadDataTask]) { - addInvocation(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) as? ([DownloadDataTask]) -> Void - perform?(`tasks`) - } - - open func saveOfflineProgress(progress: OfflineProgress) { - addInvocation(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) - let perform = methodPerformValue(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) as? (OfflineProgress) -> Void - perform?(`progress`) - } - - open func loadProgress(for blockID: String) -> OfflineProgress? { - addInvocation(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - var __value: OfflineProgress? = nil - do { - __value = try methodReturnValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))).casted() - } catch { - // do nothing - } - return __value - } - - open func loadAllOfflineProgress() -> [OfflineProgress] { - addInvocation(.m_loadAllOfflineProgress) - let perform = methodPerformValue(.m_loadAllOfflineProgress) as? () -> Void - perform?() - var __value: [OfflineProgress] - do { - __value = try methodReturnValue(.m_loadAllOfflineProgress).casted() - } catch { - onFatalFailure("Stub return value not specified for loadAllOfflineProgress(). Use given") - Failure("Stub return value not specified for loadAllOfflineProgress(). Use given") - } - return __value - } - - open func deleteProgress(for blockID: String) { - addInvocation(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - } - - open func deleteAllProgress() { - addInvocation(.m_deleteAllProgress) - let perform = methodPerformValue(.m_deleteAllProgress) as? () -> Void - perform?() - } - - open func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { - addInvocation(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) as? ([CourseBlock], DownloadQuality) -> Void - perform?(`blocks`, `downloadQuality`) - } - - open func updateTask(task: DownloadDataTask) { - addInvocation(.m_updateTask__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_updateTask__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - } - - open func downloadDataTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getDownloadDataTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasks) - let perform = methodPerformValue(.m_getDownloadDataTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasks(). Use given") - Failure("Stub return value not specified for getDownloadDataTasks(). Use given") - } - return __value - } - - open func getDownloadDataTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func deleteDownloadDataTasks(ids: [String]) { - addInvocation(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) - let perform = methodPerformValue(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) as? ([String]) -> Void - perform?(`ids`) - } - - - fileprivate enum MethodType { - case m_set__userId_userId(Parameter) - case m_getUserID - case m_publisher - case m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>) - case m_saveOfflineProgress__progress_progress(Parameter) - case m_loadProgress__for_blockID(Parameter) - case m_loadAllOfflineProgress - case m_deleteProgress__for_blockID(Parameter) - case m_deleteAllProgress - case m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>, Parameter) - case m_updateTask__task_task(Parameter) - case m_downloadDataTask__for_blockId(Parameter) - case m_getDownloadDataTasks - case m_getDownloadDataTasksForCourse__courseId(Parameter) - case m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_set__userId_userId(let lhsUserid), .m_set__userId_userId(let rhsUserid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUserid, rhs: rhsUserid, with: matcher), lhsUserid, rhsUserid, "userId")) - return Matcher.ComparisonResult(results) - - case (.m_getUserID, .m_getUserID): return .match - - case (.m_publisher, .m_publisher): return .match - - case (.m_addToDownloadQueue__tasks_tasks(let lhsTasks), .m_addToDownloadQueue__tasks_tasks(let rhsTasks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTasks, rhs: rhsTasks, with: matcher), lhsTasks, rhsTasks, "tasks")) - return Matcher.ComparisonResult(results) - - case (.m_saveOfflineProgress__progress_progress(let lhsProgress), .m_saveOfflineProgress__progress_progress(let rhsProgress)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsProgress, rhs: rhsProgress, with: matcher), lhsProgress, rhsProgress, "progress")) - return Matcher.ComparisonResult(results) - - case (.m_loadProgress__for_blockID(let lhsBlockid), .m_loadProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_loadAllOfflineProgress, .m_loadAllOfflineProgress): return .match - - case (.m_deleteProgress__for_blockID(let lhsBlockid), .m_deleteProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_deleteAllProgress, .m_deleteAllProgress): return .match - - case (.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let lhsBlocks, let lhsDownloadquality), .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let rhsBlocks, let rhsDownloadquality)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadquality, rhs: rhsDownloadquality, with: matcher), lhsDownloadquality, rhsDownloadquality, "downloadQuality")) - return Matcher.ComparisonResult(results) - - case (.m_updateTask__task_task(let lhsTask), .m_updateTask__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_downloadDataTask__for_blockId(let lhsBlockid), .m_downloadDataTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadDataTasks, .m_getDownloadDataTasks): return .match - - case (.m_getDownloadDataTasksForCourse__courseId(let lhsCourseid), .m_getDownloadDataTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_deleteDownloadDataTasks__ids_ids(let lhsIds), .m_deleteDownloadDataTasks__ids_ids(let rhsIds)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIds, rhs: rhsIds, with: matcher), lhsIds, rhsIds, "ids")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_set__userId_userId(p0): return p0.intValue - case .m_getUserID: return 0 - case .m_publisher: return 0 - case let .m_addToDownloadQueue__tasks_tasks(p0): return p0.intValue - case let .m_saveOfflineProgress__progress_progress(p0): return p0.intValue - case let .m_loadProgress__for_blockID(p0): return p0.intValue - case .m_loadAllOfflineProgress: return 0 - case let .m_deleteProgress__for_blockID(p0): return p0.intValue - case .m_deleteAllProgress: return 0 - case let .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(p0, p1): return p0.intValue + p1.intValue - case let .m_updateTask__task_task(p0): return p0.intValue - case let .m_downloadDataTask__for_blockId(p0): return p0.intValue - case .m_getDownloadDataTasks: return 0 - case let .m_getDownloadDataTasksForCourse__courseId(p0): return p0.intValue - case let .m_deleteDownloadDataTasks__ids_ids(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_set__userId_userId: return ".set(userId:)" - case .m_getUserID: return ".getUserID()" - case .m_publisher: return ".publisher()" - case .m_addToDownloadQueue__tasks_tasks: return ".addToDownloadQueue(tasks:)" - case .m_saveOfflineProgress__progress_progress: return ".saveOfflineProgress(progress:)" - case .m_loadProgress__for_blockID: return ".loadProgress(for:)" - case .m_loadAllOfflineProgress: return ".loadAllOfflineProgress()" - case .m_deleteProgress__for_blockID: return ".deleteProgress(for:)" - case .m_deleteAllProgress: return ".deleteAllProgress()" - case .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality: return ".addToDownloadQueue(blocks:downloadQuality:)" - case .m_updateTask__task_task: return ".updateTask(task:)" - case .m_downloadDataTask__for_blockId: return ".downloadDataTask(for:)" - case .m_getDownloadDataTasks: return ".getDownloadDataTasks()" - case .m_getDownloadDataTasksForCourse__courseId: return ".getDownloadDataTasksForCourse(_:)" - case .m_deleteDownloadDataTasks__ids_ids: return ".deleteDownloadDataTasks(ids:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getUserID(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @MainActor - public static func publisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_publisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadProgress(for blockID: Parameter, willReturn: OfflineProgress?...) -> MethodStub { - return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadAllOfflineProgress(willReturn: [OfflineProgress]...) -> MethodStub { - return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadDataTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getUserID(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func loadProgress(for blockID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [OfflineProgress?] = [] - let given: Given = { return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (OfflineProgress?).self) - willProduce(stubber) - return given - } - public static func loadAllOfflineProgress(willProduce: (Stubber<[OfflineProgress]>) -> Void) -> MethodStub { - let willReturn: [[OfflineProgress]] = [] - let given: Given = { return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([OfflineProgress]).self) - willProduce(stubber) - return given - } - public static func downloadDataTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - @MainActor - public static func publisher(willThrow: Error...) -> MethodStub { - return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) - } - @MainActor - public static func publisher(willProduce: (StubberThrows>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func set(userId: Parameter) -> Verify { return Verify(method: .m_set__userId_userId(`userId`))} - public static func getUserID() -> Verify { return Verify(method: .m_getUserID)} - @MainActor - public static func publisher() -> Verify { return Verify(method: .m_publisher)} - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>) -> Verify { return Verify(method: .m_addToDownloadQueue__tasks_tasks(`tasks`))} - public static func saveOfflineProgress(progress: Parameter) -> Verify { return Verify(method: .m_saveOfflineProgress__progress_progress(`progress`))} - public static func loadProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_loadProgress__for_blockID(`blockID`))} - public static func loadAllOfflineProgress() -> Verify { return Verify(method: .m_loadAllOfflineProgress)} - public static func deleteProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_deleteProgress__for_blockID(`blockID`))} - public static func deleteAllProgress() -> Verify { return Verify(method: .m_deleteAllProgress)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`))} - public static func updateTask(task: Parameter) -> Verify { return Verify(method: .m_updateTask__task_task(`task`))} - public static func downloadDataTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadDataTask__for_blockId(`blockId`))} - public static func getDownloadDataTasks() -> Verify { return Verify(method: .m_getDownloadDataTasks)} - public static func getDownloadDataTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`))} - public static func deleteDownloadDataTasks(ids: Parameter<[String]>) -> Verify { return Verify(method: .m_deleteDownloadDataTasks__ids_ids(`ids`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func set(userId: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_set__userId_userId(`userId`), performs: perform) - } - public static func getUserID(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getUserID, performs: perform) - } - @MainActor - public static func publisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_publisher, performs: perform) - } - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>, perform: @escaping ([DownloadDataTask]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__tasks_tasks(`tasks`), performs: perform) - } - public static func saveOfflineProgress(progress: Parameter, perform: @escaping (OfflineProgress) -> Void) -> Perform { - return Perform(method: .m_saveOfflineProgress__progress_progress(`progress`), performs: perform) - } - public static func loadProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_loadProgress__for_blockID(`blockID`), performs: perform) - } - public static func loadAllOfflineProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_loadAllOfflineProgress, performs: perform) - } - public static func deleteProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_deleteProgress__for_blockID(`blockID`), performs: perform) - } - public static func deleteAllProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAllProgress, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter, perform: @escaping ([CourseBlock], DownloadQuality) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`), performs: perform) - } - public static func updateTask(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_updateTask__task_task(`task`), performs: perform) - } - public static func downloadDataTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadDataTask__for_blockId(`blockId`), performs: perform) - } - public static func getDownloadDataTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasks, performs: perform) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func deleteDownloadDataTasks(ids: Parameter<[String]>, perform: @escaping ([String]) -> Void) -> Perform { - return Perform(method: .m_deleteDownloadDataTasks__ids_ids(`ids`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreStorage - -open class CoreStorageMock: CoreStorage, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var accessToken: String? { - get { invocations.append(.p_accessToken_get); return __p_accessToken ?? optionalGivenGetterValue(.p_accessToken_get, "CoreStorageMock - stub value for accessToken was not defined") } - set { invocations.append(.p_accessToken_set(.value(newValue))); __p_accessToken = newValue } - } - private var __p_accessToken: (String)? - - public var refreshToken: String? { - get { invocations.append(.p_refreshToken_get); return __p_refreshToken ?? optionalGivenGetterValue(.p_refreshToken_get, "CoreStorageMock - stub value for refreshToken was not defined") } - set { invocations.append(.p_refreshToken_set(.value(newValue))); __p_refreshToken = newValue } - } - private var __p_refreshToken: (String)? - - public var pushToken: String? { - get { invocations.append(.p_pushToken_get); return __p_pushToken ?? optionalGivenGetterValue(.p_pushToken_get, "CoreStorageMock - stub value for pushToken was not defined") } - set { invocations.append(.p_pushToken_set(.value(newValue))); __p_pushToken = newValue } - } - private var __p_pushToken: (String)? - - public var appleSignFullName: String? { - get { invocations.append(.p_appleSignFullName_get); return __p_appleSignFullName ?? optionalGivenGetterValue(.p_appleSignFullName_get, "CoreStorageMock - stub value for appleSignFullName was not defined") } - set { invocations.append(.p_appleSignFullName_set(.value(newValue))); __p_appleSignFullName = newValue } - } - private var __p_appleSignFullName: (String)? - - public var appleSignEmail: String? { - get { invocations.append(.p_appleSignEmail_get); return __p_appleSignEmail ?? optionalGivenGetterValue(.p_appleSignEmail_get, "CoreStorageMock - stub value for appleSignEmail was not defined") } - set { invocations.append(.p_appleSignEmail_set(.value(newValue))); __p_appleSignEmail = newValue } - } - private var __p_appleSignEmail: (String)? - - public var cookiesDate: Date? { - get { invocations.append(.p_cookiesDate_get); return __p_cookiesDate ?? optionalGivenGetterValue(.p_cookiesDate_get, "CoreStorageMock - stub value for cookiesDate was not defined") } - set { invocations.append(.p_cookiesDate_set(.value(newValue))); __p_cookiesDate = newValue } - } - private var __p_cookiesDate: (Date)? - - public var reviewLastShownVersion: String? { - get { invocations.append(.p_reviewLastShownVersion_get); return __p_reviewLastShownVersion ?? optionalGivenGetterValue(.p_reviewLastShownVersion_get, "CoreStorageMock - stub value for reviewLastShownVersion was not defined") } - set { invocations.append(.p_reviewLastShownVersion_set(.value(newValue))); __p_reviewLastShownVersion = newValue } - } - private var __p_reviewLastShownVersion: (String)? - - public var lastReviewDate: Date? { - get { invocations.append(.p_lastReviewDate_get); return __p_lastReviewDate ?? optionalGivenGetterValue(.p_lastReviewDate_get, "CoreStorageMock - stub value for lastReviewDate was not defined") } - set { invocations.append(.p_lastReviewDate_set(.value(newValue))); __p_lastReviewDate = newValue } - } - private var __p_lastReviewDate: (Date)? - - public var user: DataLayer.User? { - get { invocations.append(.p_user_get); return __p_user ?? optionalGivenGetterValue(.p_user_get, "CoreStorageMock - stub value for user was not defined") } - set { invocations.append(.p_user_set(.value(newValue))); __p_user = newValue } - } - private var __p_user: (DataLayer.User)? - - public var userSettings: UserSettings? { - get { invocations.append(.p_userSettings_get); return __p_userSettings ?? optionalGivenGetterValue(.p_userSettings_get, "CoreStorageMock - stub value for userSettings was not defined") } - set { invocations.append(.p_userSettings_set(.value(newValue))); __p_userSettings = newValue } - } - private var __p_userSettings: (UserSettings)? - - public var resetAppSupportDirectoryUserData: Bool? { - get { invocations.append(.p_resetAppSupportDirectoryUserData_get); return __p_resetAppSupportDirectoryUserData ?? optionalGivenGetterValue(.p_resetAppSupportDirectoryUserData_get, "CoreStorageMock - stub value for resetAppSupportDirectoryUserData was not defined") } - set { invocations.append(.p_resetAppSupportDirectoryUserData_set(.value(newValue))); __p_resetAppSupportDirectoryUserData = newValue } - } - private var __p_resetAppSupportDirectoryUserData: (Bool)? - - public var useRelativeDates: Bool { - get { invocations.append(.p_useRelativeDates_get); return __p_useRelativeDates ?? givenGetterValue(.p_useRelativeDates_get, "CoreStorageMock - stub value for useRelativeDates was not defined") } - set { invocations.append(.p_useRelativeDates_set(.value(newValue))); __p_useRelativeDates = newValue } - } - private var __p_useRelativeDates: (Bool)? - - public var lastUsedSocialAuth: String? { - get { invocations.append(.p_lastUsedSocialAuth_get); return __p_lastUsedSocialAuth ?? optionalGivenGetterValue(.p_lastUsedSocialAuth_get, "CoreStorageMock - stub value for lastUsedSocialAuth was not defined") } - set { invocations.append(.p_lastUsedSocialAuth_set(.value(newValue))); __p_lastUsedSocialAuth = newValue } - } - private var __p_lastUsedSocialAuth: (String)? - - public var latestAvailableAppVersion: String? { - get { invocations.append(.p_latestAvailableAppVersion_get); return __p_latestAvailableAppVersion ?? optionalGivenGetterValue(.p_latestAvailableAppVersion_get, "CoreStorageMock - stub value for latestAvailableAppVersion was not defined") } - set { invocations.append(.p_latestAvailableAppVersion_set(.value(newValue))); __p_latestAvailableAppVersion = newValue } - } - private var __p_latestAvailableAppVersion: (String)? - - public var updateAppRequired: Bool { - get { invocations.append(.p_updateAppRequired_get); return __p_updateAppRequired ?? givenGetterValue(.p_updateAppRequired_get, "CoreStorageMock - stub value for updateAppRequired was not defined") } - set { invocations.append(.p_updateAppRequired_set(.value(newValue))); __p_updateAppRequired = newValue } - } - private var __p_updateAppRequired: (Bool)? - - - - - - open func clear() { - addInvocation(.m_clear) - let perform = methodPerformValue(.m_clear) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_clear - case p_accessToken_get - case p_accessToken_set(Parameter) - case p_refreshToken_get - case p_refreshToken_set(Parameter) - case p_pushToken_get - case p_pushToken_set(Parameter) - case p_appleSignFullName_get - case p_appleSignFullName_set(Parameter) - case p_appleSignEmail_get - case p_appleSignEmail_set(Parameter) - case p_cookiesDate_get - case p_cookiesDate_set(Parameter) - case p_reviewLastShownVersion_get - case p_reviewLastShownVersion_set(Parameter) - case p_lastReviewDate_get - case p_lastReviewDate_set(Parameter) - case p_user_get - case p_user_set(Parameter) - case p_userSettings_get - case p_userSettings_set(Parameter) - case p_resetAppSupportDirectoryUserData_get - case p_resetAppSupportDirectoryUserData_set(Parameter) - case p_useRelativeDates_get - case p_useRelativeDates_set(Parameter) - case p_lastUsedSocialAuth_get - case p_lastUsedSocialAuth_set(Parameter) - case p_latestAvailableAppVersion_get - case p_latestAvailableAppVersion_set(Parameter) - case p_updateAppRequired_get - case p_updateAppRequired_set(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_clear, .m_clear): return .match - case (.p_accessToken_get,.p_accessToken_get): return Matcher.ComparisonResult.match - case (.p_accessToken_set(let left),.p_accessToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_refreshToken_get,.p_refreshToken_get): return Matcher.ComparisonResult.match - case (.p_refreshToken_set(let left),.p_refreshToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_pushToken_get,.p_pushToken_get): return Matcher.ComparisonResult.match - case (.p_pushToken_set(let left),.p_pushToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignFullName_get,.p_appleSignFullName_get): return Matcher.ComparisonResult.match - case (.p_appleSignFullName_set(let left),.p_appleSignFullName_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignEmail_get,.p_appleSignEmail_get): return Matcher.ComparisonResult.match - case (.p_appleSignEmail_set(let left),.p_appleSignEmail_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_cookiesDate_get,.p_cookiesDate_get): return Matcher.ComparisonResult.match - case (.p_cookiesDate_set(let left),.p_cookiesDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_reviewLastShownVersion_get,.p_reviewLastShownVersion_get): return Matcher.ComparisonResult.match - case (.p_reviewLastShownVersion_set(let left),.p_reviewLastShownVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastReviewDate_get,.p_lastReviewDate_get): return Matcher.ComparisonResult.match - case (.p_lastReviewDate_set(let left),.p_lastReviewDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_user_get,.p_user_get): return Matcher.ComparisonResult.match - case (.p_user_set(let left),.p_user_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_userSettings_get,.p_userSettings_get): return Matcher.ComparisonResult.match - case (.p_userSettings_set(let left),.p_userSettings_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_resetAppSupportDirectoryUserData_get,.p_resetAppSupportDirectoryUserData_get): return Matcher.ComparisonResult.match - case (.p_resetAppSupportDirectoryUserData_set(let left),.p_resetAppSupportDirectoryUserData_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_useRelativeDates_get,.p_useRelativeDates_get): return Matcher.ComparisonResult.match - case (.p_useRelativeDates_set(let left),.p_useRelativeDates_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastUsedSocialAuth_get,.p_lastUsedSocialAuth_get): return Matcher.ComparisonResult.match - case (.p_lastUsedSocialAuth_set(let left),.p_lastUsedSocialAuth_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_latestAvailableAppVersion_get,.p_latestAvailableAppVersion_get): return Matcher.ComparisonResult.match - case (.p_latestAvailableAppVersion_set(let left),.p_latestAvailableAppVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_updateAppRequired_get,.p_updateAppRequired_get): return Matcher.ComparisonResult.match - case (.p_updateAppRequired_set(let left),.p_updateAppRequired_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_clear: return 0 - case .p_accessToken_get: return 0 - case .p_accessToken_set(let newValue): return newValue.intValue - case .p_refreshToken_get: return 0 - case .p_refreshToken_set(let newValue): return newValue.intValue - case .p_pushToken_get: return 0 - case .p_pushToken_set(let newValue): return newValue.intValue - case .p_appleSignFullName_get: return 0 - case .p_appleSignFullName_set(let newValue): return newValue.intValue - case .p_appleSignEmail_get: return 0 - case .p_appleSignEmail_set(let newValue): return newValue.intValue - case .p_cookiesDate_get: return 0 - case .p_cookiesDate_set(let newValue): return newValue.intValue - case .p_reviewLastShownVersion_get: return 0 - case .p_reviewLastShownVersion_set(let newValue): return newValue.intValue - case .p_lastReviewDate_get: return 0 - case .p_lastReviewDate_set(let newValue): return newValue.intValue - case .p_user_get: return 0 - case .p_user_set(let newValue): return newValue.intValue - case .p_userSettings_get: return 0 - case .p_userSettings_set(let newValue): return newValue.intValue - case .p_resetAppSupportDirectoryUserData_get: return 0 - case .p_resetAppSupportDirectoryUserData_set(let newValue): return newValue.intValue - case .p_useRelativeDates_get: return 0 - case .p_useRelativeDates_set(let newValue): return newValue.intValue - case .p_lastUsedSocialAuth_get: return 0 - case .p_lastUsedSocialAuth_set(let newValue): return newValue.intValue - case .p_latestAvailableAppVersion_get: return 0 - case .p_latestAvailableAppVersion_set(let newValue): return newValue.intValue - case .p_updateAppRequired_get: return 0 - case .p_updateAppRequired_set(let newValue): return newValue.intValue - } - } - func assertionName() -> String { - switch self { - case .m_clear: return ".clear()" - case .p_accessToken_get: return "[get] .accessToken" - case .p_accessToken_set: return "[set] .accessToken" - case .p_refreshToken_get: return "[get] .refreshToken" - case .p_refreshToken_set: return "[set] .refreshToken" - case .p_pushToken_get: return "[get] .pushToken" - case .p_pushToken_set: return "[set] .pushToken" - case .p_appleSignFullName_get: return "[get] .appleSignFullName" - case .p_appleSignFullName_set: return "[set] .appleSignFullName" - case .p_appleSignEmail_get: return "[get] .appleSignEmail" - case .p_appleSignEmail_set: return "[set] .appleSignEmail" - case .p_cookiesDate_get: return "[get] .cookiesDate" - case .p_cookiesDate_set: return "[set] .cookiesDate" - case .p_reviewLastShownVersion_get: return "[get] .reviewLastShownVersion" - case .p_reviewLastShownVersion_set: return "[set] .reviewLastShownVersion" - case .p_lastReviewDate_get: return "[get] .lastReviewDate" - case .p_lastReviewDate_set: return "[set] .lastReviewDate" - case .p_user_get: return "[get] .user" - case .p_user_set: return "[set] .user" - case .p_userSettings_get: return "[get] .userSettings" - case .p_userSettings_set: return "[set] .userSettings" - case .p_resetAppSupportDirectoryUserData_get: return "[get] .resetAppSupportDirectoryUserData" - case .p_resetAppSupportDirectoryUserData_set: return "[set] .resetAppSupportDirectoryUserData" - case .p_useRelativeDates_get: return "[get] .useRelativeDates" - case .p_useRelativeDates_set: return "[set] .useRelativeDates" - case .p_lastUsedSocialAuth_get: return "[get] .lastUsedSocialAuth" - case .p_lastUsedSocialAuth_set: return "[set] .lastUsedSocialAuth" - case .p_latestAvailableAppVersion_get: return "[get] .latestAvailableAppVersion" - case .p_latestAvailableAppVersion_set: return "[set] .latestAvailableAppVersion" - case .p_updateAppRequired_get: return "[get] .updateAppRequired" - case .p_updateAppRequired_set: return "[set] .updateAppRequired" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func accessToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_accessToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func refreshToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_refreshToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func pushToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_pushToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignFullName(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignFullName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignEmail(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func cookiesDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_cookiesDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func reviewLastShownVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_reviewLastShownVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastReviewDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_lastReviewDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func user(getter defaultValue: DataLayer.User?...) -> PropertyStub { - return Given(method: .p_user_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func userSettings(getter defaultValue: UserSettings?...) -> PropertyStub { - return Given(method: .p_userSettings_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func resetAppSupportDirectoryUserData(getter defaultValue: Bool?...) -> PropertyStub { - return Given(method: .p_resetAppSupportDirectoryUserData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func useRelativeDates(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_useRelativeDates_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastUsedSocialAuth(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_lastUsedSocialAuth_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func latestAvailableAppVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_latestAvailableAppVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func updateAppRequired(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_updateAppRequired_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func clear() -> Verify { return Verify(method: .m_clear)} - public static var accessToken: Verify { return Verify(method: .p_accessToken_get) } - public static func accessToken(set newValue: Parameter) -> Verify { return Verify(method: .p_accessToken_set(newValue)) } - public static var refreshToken: Verify { return Verify(method: .p_refreshToken_get) } - public static func refreshToken(set newValue: Parameter) -> Verify { return Verify(method: .p_refreshToken_set(newValue)) } - public static var pushToken: Verify { return Verify(method: .p_pushToken_get) } - public static func pushToken(set newValue: Parameter) -> Verify { return Verify(method: .p_pushToken_set(newValue)) } - public static var appleSignFullName: Verify { return Verify(method: .p_appleSignFullName_get) } - public static func appleSignFullName(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignFullName_set(newValue)) } - public static var appleSignEmail: Verify { return Verify(method: .p_appleSignEmail_get) } - public static func appleSignEmail(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignEmail_set(newValue)) } - public static var cookiesDate: Verify { return Verify(method: .p_cookiesDate_get) } - public static func cookiesDate(set newValue: Parameter) -> Verify { return Verify(method: .p_cookiesDate_set(newValue)) } - public static var reviewLastShownVersion: Verify { return Verify(method: .p_reviewLastShownVersion_get) } - public static func reviewLastShownVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_reviewLastShownVersion_set(newValue)) } - public static var lastReviewDate: Verify { return Verify(method: .p_lastReviewDate_get) } - public static func lastReviewDate(set newValue: Parameter) -> Verify { return Verify(method: .p_lastReviewDate_set(newValue)) } - public static var user: Verify { return Verify(method: .p_user_get) } - public static func user(set newValue: Parameter) -> Verify { return Verify(method: .p_user_set(newValue)) } - public static var userSettings: Verify { return Verify(method: .p_userSettings_get) } - public static func userSettings(set newValue: Parameter) -> Verify { return Verify(method: .p_userSettings_set(newValue)) } - public static var resetAppSupportDirectoryUserData: Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_get) } - public static func resetAppSupportDirectoryUserData(set newValue: Parameter) -> Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_set(newValue)) } - public static var useRelativeDates: Verify { return Verify(method: .p_useRelativeDates_get) } - public static func useRelativeDates(set newValue: Parameter) -> Verify { return Verify(method: .p_useRelativeDates_set(newValue)) } - public static var lastUsedSocialAuth: Verify { return Verify(method: .p_lastUsedSocialAuth_get) } - public static func lastUsedSocialAuth(set newValue: Parameter) -> Verify { return Verify(method: .p_lastUsedSocialAuth_set(newValue)) } - public static var latestAvailableAppVersion: Verify { return Verify(method: .p_latestAvailableAppVersion_get) } - public static func latestAvailableAppVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_latestAvailableAppVersion_set(newValue)) } - public static var updateAppRequired: Verify { return Verify(method: .p_updateAppRequired_get) } - public static func updateAppRequired(set newValue: Parameter) -> Verify { return Verify(method: .p_updateAppRequired_set(newValue)) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func clear(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_clear, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CourseStructureManagerProtocol - -open class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getLoadedCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func shiftDueDates(courseID: String) throws { - addInvocation(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - do { - _ = try methodReturnValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - - fileprivate enum MethodType { - case m_getCourseBlocks__courseID_courseID(Parameter) - case m_getLoadedCourseBlocks__courseID_courseID(Parameter) - case m_shiftDueDates__courseID_courseID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseBlocks__courseID_courseID(let lhsCourseid), .m_getCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getLoadedCourseBlocks__courseID_courseID(let lhsCourseid), .m_getLoadedCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_shiftDueDates__courseID_courseID(let lhsCourseid), .m_shiftDueDates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_getLoadedCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_shiftDueDates__courseID_courseID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getCourseBlocks__courseID_courseID: return ".getCourseBlocks(courseID:)" - case .m_getLoadedCourseBlocks__courseID_courseID: return ".getLoadedCourseBlocks(courseID:)" - case .m_shiftDueDates__courseID_courseID: return ".shiftDueDates(courseID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getLoadedCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func shiftDueDates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func shiftDueDates(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseBlocks__courseID_courseID(`courseID`))} - public static func getLoadedCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`))} - public static func shiftDueDates(courseID: Parameter) -> Verify { return Verify(method: .m_shiftDueDates__courseID_courseID(`courseID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func getLoadedCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func shiftDueDates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_shiftDueDates__courseID_courseID(`courseID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DownloadManagerProtocol - -open class DownloadManagerProtocolMock: DownloadManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCurrentDownloadTask() -> DownloadDataTask? { - addInvocation(.m_getCurrentDownloadTask) - let perform = methodPerformValue(.m_getCurrentDownloadTask) as? () -> Void - perform?() - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_getCurrentDownloadTask).casted() - } catch { - // do nothing - } - return __value - } - - open func eventPublisher() -> AnyPublisher { - addInvocation(.m_eventPublisher) - let perform = methodPerformValue(.m_eventPublisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_eventPublisher).casted() - } catch { - onFatalFailure("Stub return value not specified for eventPublisher(). Use given") - Failure("Stub return value not specified for eventPublisher(). Use given") - } - return __value - } - - open func addToDownloadQueue(blocks: [CourseBlock]) throws { - addInvocation(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - do { - _ = try methodReturnValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getDownloadTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasks) - let perform = methodPerformValue(.m_getDownloadTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasks(). Use given") - Failure("Stub return value not specified for getDownloadTasks(). Use given") - } - return __value - } - - open func getDownloadTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func cancelDownloading(courseId: String, blocks: [CourseBlock]) throws { - addInvocation(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) as? (String, [CourseBlock]) -> Void - perform?(`courseId`, `blocks`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(task: DownloadDataTask) throws { - addInvocation(.m_cancelDownloading__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_cancelDownloading__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - do { - _ = try methodReturnValue(.m_cancelDownloading__task_task(Parameter.value(`task`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(courseId: String) throws { - addInvocation(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelAllDownloading() throws { - addInvocation(.m_cancelAllDownloading) - let perform = methodPerformValue(.m_cancelAllDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_cancelAllDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func deleteAll() { - addInvocation(.m_deleteAll) - let perform = methodPerformValue(.m_deleteAll) as? () -> Void - perform?() - } - - open func fileUrl(for blockId: String) -> URL? { - addInvocation(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: URL? = nil - do { - __value = try methodReturnValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func resumeDownloading() throws { - addInvocation(.m_resumeDownloading) - let perform = methodPerformValue(.m_resumeDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_resumeDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func isLargeVideosSize(blocks: [CourseBlock]) -> Bool { - addInvocation(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - Failure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - } - return __value - } - - open func removeAppSupportDirectoryUnusedContent() { - addInvocation(.m_removeAppSupportDirectoryUnusedContent) - let perform = methodPerformValue(.m_removeAppSupportDirectoryUnusedContent) as? () -> Void - perform?() - } - - open func delete(blocks: [CourseBlock], courseId: String) { - addInvocation(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) as? ([CourseBlock], String) -> Void - perform?(`blocks`, `courseId`) - } - - open func downloadTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getFreeDiskSpace() -> Int? { - addInvocation(.m_getFreeDiskSpace) - let perform = methodPerformValue(.m_getFreeDiskSpace) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getFreeDiskSpace).casted() - } catch { - // do nothing - } - return __value - } - - - fileprivate enum MethodType { - case m_getCurrentDownloadTask - case m_eventPublisher - case m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>) - case m_getDownloadTasks - case m_getDownloadTasksForCourse__courseId(Parameter) - case m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter, Parameter<[CourseBlock]>) - case m_cancelDownloading__task_task(Parameter) - case m_cancelDownloading__courseId_courseId(Parameter) - case m_cancelAllDownloading - case m_deleteAll - case m_fileUrl__for_blockId(Parameter) - case m_resumeDownloading - case m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>) - case m_removeAppSupportDirectoryUnusedContent - case m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>, Parameter) - case m_downloadTask__for_blockId(Parameter) - case m_getFreeDiskSpace - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCurrentDownloadTask, .m_getCurrentDownloadTask): return .match - - case (.m_eventPublisher, .m_eventPublisher): return .match - - case (.m_addToDownloadQueue__blocks_blocks(let lhsBlocks), .m_addToDownloadQueue__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadTasks, .m_getDownloadTasks): return .match - - case (.m_getDownloadTasksForCourse__courseId(let lhsCourseid), .m_getDownloadTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseIdblocks_blocks(let lhsCourseid, let lhsBlocks), .m_cancelDownloading__courseId_courseIdblocks_blocks(let rhsCourseid, let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__task_task(let lhsTask), .m_cancelDownloading__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseId(let lhsCourseid), .m_cancelDownloading__courseId_courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelAllDownloading, .m_cancelAllDownloading): return .match - - case (.m_deleteAll, .m_deleteAll): return .match - - case (.m_fileUrl__for_blockId(let lhsBlockid), .m_fileUrl__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_resumeDownloading, .m_resumeDownloading): return .match - - case (.m_isLargeVideosSize__blocks_blocks(let lhsBlocks), .m_isLargeVideosSize__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_removeAppSupportDirectoryUnusedContent, .m_removeAppSupportDirectoryUnusedContent): return .match - - case (.m_delete__blocks_blockscourseId_courseId(let lhsBlocks, let lhsCourseid), .m_delete__blocks_blockscourseId_courseId(let rhsBlocks, let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_downloadTask__for_blockId(let lhsBlockid), .m_downloadTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getFreeDiskSpace, .m_getFreeDiskSpace): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_getCurrentDownloadTask: return 0 - case .m_eventPublisher: return 0 - case let .m_addToDownloadQueue__blocks_blocks(p0): return p0.intValue - case .m_getDownloadTasks: return 0 - case let .m_getDownloadTasksForCourse__courseId(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseIdblocks_blocks(p0, p1): return p0.intValue + p1.intValue - case let .m_cancelDownloading__task_task(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseId(p0): return p0.intValue - case .m_cancelAllDownloading: return 0 - case .m_deleteAll: return 0 - case let .m_fileUrl__for_blockId(p0): return p0.intValue - case .m_resumeDownloading: return 0 - case let .m_isLargeVideosSize__blocks_blocks(p0): return p0.intValue - case .m_removeAppSupportDirectoryUnusedContent: return 0 - case let .m_delete__blocks_blockscourseId_courseId(p0, p1): return p0.intValue + p1.intValue - case let .m_downloadTask__for_blockId(p0): return p0.intValue - case .m_getFreeDiskSpace: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_getCurrentDownloadTask: return ".getCurrentDownloadTask()" - case .m_eventPublisher: return ".eventPublisher()" - case .m_addToDownloadQueue__blocks_blocks: return ".addToDownloadQueue(blocks:)" - case .m_getDownloadTasks: return ".getDownloadTasks()" - case .m_getDownloadTasksForCourse__courseId: return ".getDownloadTasksForCourse(_:)" - case .m_cancelDownloading__courseId_courseIdblocks_blocks: return ".cancelDownloading(courseId:blocks:)" - case .m_cancelDownloading__task_task: return ".cancelDownloading(task:)" - case .m_cancelDownloading__courseId_courseId: return ".cancelDownloading(courseId:)" - case .m_cancelAllDownloading: return ".cancelAllDownloading()" - case .m_deleteAll: return ".deleteAll()" - case .m_fileUrl__for_blockId: return ".fileUrl(for:)" - case .m_resumeDownloading: return ".resumeDownloading()" - case .m_isLargeVideosSize__blocks_blocks: return ".isLargeVideosSize(blocks:)" - case .m_removeAppSupportDirectoryUnusedContent: return ".removeAppSupportDirectoryUnusedContent()" - case .m_delete__blocks_blockscourseId_courseId: return ".delete(blocks:courseId:)" - case .m_downloadTask__for_blockId: return ".downloadTask(for:)" - case .m_getFreeDiskSpace: return ".getFreeDiskSpace()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCurrentDownloadTask(willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func eventPublisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func fileUrl(for blockId: Parameter, willReturn: URL?...) -> MethodStub { - return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getFreeDiskSpace(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCurrentDownloadTask(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func eventPublisher(willProduce: (Stubber>) -> Void) -> MethodStub { - let willReturn: [AnyPublisher] = [] - let given: Given = { return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - public static func getDownloadTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func fileUrl(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [URL?] = [] - let given: Given = { return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (URL?).self) - willProduce(stubber) - return given - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func downloadTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getFreeDiskSpace(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(task: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(task: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelAllDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelAllDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func resumeDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resumeDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCurrentDownloadTask() -> Verify { return Verify(method: .m_getCurrentDownloadTask)} - public static func eventPublisher() -> Verify { return Verify(method: .m_eventPublisher)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocks(`blocks`))} - public static func getDownloadTasks() -> Verify { return Verify(method: .m_getDownloadTasks)} - public static func getDownloadTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadTasksForCourse__courseId(`courseId`))} - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`))} - public static func cancelDownloading(task: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__task_task(`task`))} - public static func cancelDownloading(courseId: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseId(`courseId`))} - public static func cancelAllDownloading() -> Verify { return Verify(method: .m_cancelAllDownloading)} - public static func deleteAll() -> Verify { return Verify(method: .m_deleteAll)} - public static func fileUrl(for blockId: Parameter) -> Verify { return Verify(method: .m_fileUrl__for_blockId(`blockId`))} - public static func resumeDownloading() -> Verify { return Verify(method: .m_resumeDownloading)} - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_isLargeVideosSize__blocks_blocks(`blocks`))} - public static func removeAppSupportDirectoryUnusedContent() -> Verify { return Verify(method: .m_removeAppSupportDirectoryUnusedContent)} - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter) -> Verify { return Verify(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`))} - public static func downloadTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadTask__for_blockId(`blockId`))} - public static func getFreeDiskSpace() -> Verify { return Verify(method: .m_getFreeDiskSpace)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCurrentDownloadTask(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getCurrentDownloadTask, performs: perform) - } - public static func eventPublisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_eventPublisher, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), performs: perform) - } - public static func getDownloadTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadTasks, performs: perform) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, perform: @escaping (String, [CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), performs: perform) - } - public static func cancelDownloading(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__task_task(`task`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseId(`courseId`), performs: perform) - } - public static func cancelAllDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_cancelAllDownloading, performs: perform) - } - public static func deleteAll(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAll, performs: perform) - } - public static func fileUrl(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_fileUrl__for_blockId(`blockId`), performs: perform) - } - public static func resumeDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_resumeDownloading, performs: perform) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), performs: perform) - } - public static func removeAppSupportDirectoryUnusedContent(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeAppSupportDirectoryUnusedContent, performs: perform) - } - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter, perform: @escaping ([CourseBlock], String) -> Void) -> Perform { - return Perform(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`), performs: perform) - } - public static func downloadTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadTask__for_blockId(`blockId`), performs: perform) - } - public static func getFreeDiskSpace(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getFreeDiskSpace, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - OfflineSyncInteractorProtocol - -open class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func submitOfflineProgress(courseID: String, blockID: String, data: String) throws -> Bool { - addInvocation(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) - let perform = methodPerformValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) as? (String, String, String) -> Void - perform?(`courseID`, `blockID`, `data`) - var __value: Bool - do { - __value = try methodReturnValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - Failure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter, Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let lhsCourseid, let lhsBlockid, let lhsData), .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let rhsCourseid, let rhsBlockid, let rhsData)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsData, rhs: rhsData, with: matcher), lhsData, rhsData, "data")) - return Matcher.ComparisonResult(results) - } - } - - func intValue() -> Int { - switch self { - case let .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data: return ".submitOfflineProgress(courseID:blockID:data:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter) -> Verify { return Verify(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - diff --git a/Authorization/AuthorizationTests/Generated/AuthorizationMocks.generated.swift b/Authorization/AuthorizationTests/Generated/AuthorizationMocks.generated.swift new file mode 100644 index 000000000..9d91b858d --- /dev/null +++ b/Authorization/AuthorizationTests/Generated/AuthorizationMocks.generated.swift @@ -0,0 +1,2267 @@ +/// +/// @Generated by Mockolo +/// + + + +import Alamofire +@testable import Authorization +import Combine +@testable import Core +import CoreData +import Foundation +import OEXFoundation +import SwiftUI +import ZipArchive + + +public final class ConfigProtocolMock: ConfigProtocol, @unchecked Sendable { + public init() { } + public init(baseURL: URL = URL(fileURLWithPath: ""), baseSSOURL: URL = URL(fileURLWithPath: ""), ssoFinishedURL: URL = URL(fileURLWithPath: ""), ssoButtonTitle: [String: Any] = [String: Any](), oAuthClientId: String = "", tokenType: TokenType, feedbackEmail: String = "", appStoreLink: String = "", faq: URL? = nil, platformName: String = "", agreement: AgreementConfig, firebase: FirebaseConfig, facebook: FacebookConfig, microsoft: MicrosoftConfig, google: GoogleConfig, appleSignIn: AppleSignInConfig, features: FeaturesConfig, theme: ThemeConfig, uiComponents: UIComponentsConfig, discovery: DiscoveryConfig, dashboard: DashboardConfig, braze: BrazeConfig, branch: BranchConfig, program: DiscoveryConfig, experimentalFeatures: ExperimentalFeaturesConfig, URIScheme: String = "") { + self.baseURL = baseURL + self.baseSSOURL = baseSSOURL + self.ssoFinishedURL = ssoFinishedURL + self.ssoButtonTitle = ssoButtonTitle + self.oAuthClientId = oAuthClientId + self._tokenType = tokenType + self.feedbackEmail = feedbackEmail + self.appStoreLink = appStoreLink + self.faq = faq + self.platformName = platformName + self._agreement = agreement + self._firebase = firebase + self._facebook = facebook + self._microsoft = microsoft + self._google = google + self._appleSignIn = appleSignIn + self._features = features + self._theme = theme + self._uiComponents = uiComponents + self._discovery = discovery + self._dashboard = dashboard + self._braze = braze + self._branch = branch + self._program = program + self._experimentalFeatures = experimentalFeatures + self.URIScheme = URIScheme + } + + + + public var baseURL: URL = URL(fileURLWithPath: "") + + + public var baseSSOURL: URL = URL(fileURLWithPath: "") + + + public var ssoFinishedURL: URL = URL(fileURLWithPath: "") + + + public var ssoButtonTitle: [String: Any] = [String: Any]() + + + public var oAuthClientId: String = "" + + + private var _tokenType: TokenType! + public var tokenType: TokenType { + get { return _tokenType } + set { _tokenType = newValue } + } + + + public var feedbackEmail: String = "" + + + public var appStoreLink: String = "" + + + public var faq: URL? = nil + + + public var platformName: String = "" + + + private var _agreement: AgreementConfig! + public var agreement: AgreementConfig { + get { return _agreement } + set { _agreement = newValue } + } + + + private var _firebase: FirebaseConfig! + public var firebase: FirebaseConfig { + get { return _firebase } + set { _firebase = newValue } + } + + + private var _facebook: FacebookConfig! + public var facebook: FacebookConfig { + get { return _facebook } + set { _facebook = newValue } + } + + + private var _microsoft: MicrosoftConfig! + public var microsoft: MicrosoftConfig { + get { return _microsoft } + set { _microsoft = newValue } + } + + + private var _google: GoogleConfig! + public var google: GoogleConfig { + get { return _google } + set { _google = newValue } + } + + + private var _appleSignIn: AppleSignInConfig! + public var appleSignIn: AppleSignInConfig { + get { return _appleSignIn } + set { _appleSignIn = newValue } + } + + + private var _features: FeaturesConfig! + public var features: FeaturesConfig { + get { return _features } + set { _features = newValue } + } + + + private var _theme: ThemeConfig! + public var theme: ThemeConfig { + get { return _theme } + set { _theme = newValue } + } + + + private var _uiComponents: UIComponentsConfig! + public var uiComponents: UIComponentsConfig { + get { return _uiComponents } + set { _uiComponents = newValue } + } + + + private var _discovery: DiscoveryConfig! + public var discovery: DiscoveryConfig { + get { return _discovery } + set { _discovery = newValue } + } + + + private var _dashboard: DashboardConfig! + public var dashboard: DashboardConfig { + get { return _dashboard } + set { _dashboard = newValue } + } + + + private var _braze: BrazeConfig! + public var braze: BrazeConfig { + get { return _braze } + set { _braze = newValue } + } + + + private var _branch: BranchConfig! + public var branch: BranchConfig { + get { return _branch } + set { _branch = newValue } + } + + + private var _program: DiscoveryConfig! + public var program: DiscoveryConfig { + get { return _program } + set { _program = newValue } + } + + + private var _experimentalFeatures: ExperimentalFeaturesConfig! + public var experimentalFeatures: ExperimentalFeaturesConfig { + get { return _experimentalFeatures } + set { _experimentalFeatures = newValue } + } + + + public var URIScheme: String = "" +} + +public final class CoreAnalyticsMock: CoreAnalytics { + public init() { } + + + public private(set) var trackEventCallCount = 0 + public var trackEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackEventCallCount += 1 + if let trackEventHandler = trackEventHandler { + trackEventHandler(event, parameters) + } + + } + + public private(set) var trackEventBiValueCallCount = 0 + public var trackEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackEventBiValueCallCount += 1 + if let trackEventBiValueHandler = trackEventBiValueHandler { + trackEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var trackScreenEventCallCount = 0 + public var trackScreenEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackScreenEventCallCount += 1 + if let trackScreenEventHandler = trackScreenEventHandler { + trackScreenEventHandler(event, parameters) + } + + } + + public private(set) var trackScreenEventBiValueCallCount = 0 + public var trackScreenEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackScreenEventBiValueCallCount += 1 + if let trackScreenEventBiValueHandler = trackScreenEventBiValueHandler { + trackScreenEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var appreviewCallCount = 0 + public var appreviewHandler: ((AnalyticsEvent, EventBIValue, String?, Int?) -> ())? + public func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { + appreviewCallCount += 1 + if let appreviewHandler = appreviewHandler { + appreviewHandler(event, biValue, action, rating) + } + + } + + public private(set) var videoQualityChangedCallCount = 0 + public var videoQualityChangedHandler: ((AnalyticsEvent, EventBIValue, String, String) -> ())? + public func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { + videoQualityChangedCallCount += 1 + if let videoQualityChangedHandler = videoQualityChangedHandler { + videoQualityChangedHandler(event, bivalue, value, oldValue) + } + + } +} + +public final class CoreStorageMock: CoreStorage, @unchecked Sendable { + public init() { } + public init(accessToken: String? = nil, refreshToken: String? = nil, pushToken: String? = nil, appleSignFullName: String? = nil, appleSignEmail: String? = nil, cookiesDate: Date? = nil, reviewLastShownVersion: String? = nil, lastReviewDate: Date? = nil, user: DataLayer.User? = nil, userSettings: UserSettings? = nil, resetAppSupportDirectoryUserData: Bool? = nil, useRelativeDates: Bool = false, lastUsedSocialAuth: String? = nil, latestAvailableAppVersion: String? = nil, updateAppRequired: Bool = false) { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.pushToken = pushToken + self.appleSignFullName = appleSignFullName + self.appleSignEmail = appleSignEmail + self.cookiesDate = cookiesDate + self.reviewLastShownVersion = reviewLastShownVersion + self.lastReviewDate = lastReviewDate + self.user = user + self.userSettings = userSettings + self.resetAppSupportDirectoryUserData = resetAppSupportDirectoryUserData + self.useRelativeDates = useRelativeDates + self.lastUsedSocialAuth = lastUsedSocialAuth + self.latestAvailableAppVersion = latestAvailableAppVersion + self.updateAppRequired = updateAppRequired + } + + + public private(set) var accessTokenSetCallCount = 0 + public var accessToken: String? = nil { didSet { accessTokenSetCallCount += 1 } } + + public private(set) var refreshTokenSetCallCount = 0 + public var refreshToken: String? = nil { didSet { refreshTokenSetCallCount += 1 } } + + public private(set) var pushTokenSetCallCount = 0 + public var pushToken: String? = nil { didSet { pushTokenSetCallCount += 1 } } + + public private(set) var appleSignFullNameSetCallCount = 0 + public var appleSignFullName: String? = nil { didSet { appleSignFullNameSetCallCount += 1 } } + + public private(set) var appleSignEmailSetCallCount = 0 + public var appleSignEmail: String? = nil { didSet { appleSignEmailSetCallCount += 1 } } + + public private(set) var cookiesDateSetCallCount = 0 + public var cookiesDate: Date? = nil { didSet { cookiesDateSetCallCount += 1 } } + + public private(set) var reviewLastShownVersionSetCallCount = 0 + public var reviewLastShownVersion: String? = nil { didSet { reviewLastShownVersionSetCallCount += 1 } } + + public private(set) var lastReviewDateSetCallCount = 0 + public var lastReviewDate: Date? = nil { didSet { lastReviewDateSetCallCount += 1 } } + + public private(set) var userSetCallCount = 0 + public var user: DataLayer.User? = nil { didSet { userSetCallCount += 1 } } + + public private(set) var userSettingsSetCallCount = 0 + public var userSettings: UserSettings? = nil { didSet { userSettingsSetCallCount += 1 } } + + public private(set) var resetAppSupportDirectoryUserDataSetCallCount = 0 + public var resetAppSupportDirectoryUserData: Bool? = nil { didSet { resetAppSupportDirectoryUserDataSetCallCount += 1 } } + + public private(set) var useRelativeDatesSetCallCount = 0 + public var useRelativeDates: Bool = false { didSet { useRelativeDatesSetCallCount += 1 } } + + public private(set) var lastUsedSocialAuthSetCallCount = 0 + public var lastUsedSocialAuth: String? = nil { didSet { lastUsedSocialAuthSetCallCount += 1 } } + + public private(set) var latestAvailableAppVersionSetCallCount = 0 + public var latestAvailableAppVersion: String? = nil { didSet { latestAvailableAppVersionSetCallCount += 1 } } + + public private(set) var updateAppRequiredSetCallCount = 0 + public var updateAppRequired: Bool = false { didSet { updateAppRequiredSetCallCount += 1 } } + + private let clearState = MockoloMutex(MockoloHandlerState ()>()) + public var clearCallCount: Int { + return clearState.withLock(\.callCount) + } + public var clearHandler: (@Sendable () -> ())? { + get { clearState.withLock(\.handler) } + set { clearState.withLock { $0.handler = newValue } } + } + public func clear() { + let clearHandler = clearState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearHandler = clearHandler { + clearHandler() + } + + } +} + +public final class AuthInteractorProtocolMock: AuthInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let loginState = MockoloMutex(MockoloHandlerState User>()) + public var loginCallCount: Int { + return loginState.withLock(\.callCount) + } + public var loginHandler: (@Sendable (String, String) async throws -> User)? { + get { loginState.withLock(\.handler) } + set { loginState.withLock { $0.handler = newValue } } + } + public func login(username: String, password: String) async throws -> User { + let loginHandler = loginState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginHandler = loginHandler { + return try await loginHandler(username, password) + } + fatalError("loginHandler returns can't have a default value thus its handler must be set") + } + + private let loginExternalTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginExternalTokenCallCount: Int { + return loginExternalTokenState.withLock(\.callCount) + } + public var loginExternalTokenHandler: (@Sendable (String, String) async throws -> User)? { + get { loginExternalTokenState.withLock(\.handler) } + set { loginExternalTokenState.withLock { $0.handler = newValue } } + } + public func login(externalToken: String, backend: String) async throws -> User { + let loginExternalTokenHandler = loginExternalTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginExternalTokenHandler = loginExternalTokenHandler { + return try await loginExternalTokenHandler(externalToken, backend) + } + fatalError("loginExternalTokenHandler returns can't have a default value thus its handler must be set") + } + + private let loginSsoTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginSsoTokenCallCount: Int { + return loginSsoTokenState.withLock(\.callCount) + } + public var loginSsoTokenHandler: (@Sendable (String) async throws -> User)? { + get { loginSsoTokenState.withLock(\.handler) } + set { loginSsoTokenState.withLock { $0.handler = newValue } } + } + public func login(ssoToken: String) async throws -> User { + let loginSsoTokenHandler = loginSsoTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginSsoTokenHandler = loginSsoTokenHandler { + return try await loginSsoTokenHandler(ssoToken) + } + fatalError("loginSsoTokenHandler returns can't have a default value thus its handler must be set") + } + + private let resetPasswordState = MockoloMutex(MockoloHandlerState ResetPassword>()) + public var resetPasswordCallCount: Int { + return resetPasswordState.withLock(\.callCount) + } + public var resetPasswordHandler: (@Sendable (String) async throws -> ResetPassword)? { + get { resetPasswordState.withLock(\.handler) } + set { resetPasswordState.withLock { $0.handler = newValue } } + } + public func resetPassword(email: String) async throws -> ResetPassword { + let resetPasswordHandler = resetPasswordState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resetPasswordHandler = resetPasswordHandler { + return try await resetPasswordHandler(email) + } + fatalError("resetPasswordHandler returns can't have a default value thus its handler must be set") + } + + private let getCookiesState = MockoloMutex(MockoloHandlerState ()>()) + public var getCookiesCallCount: Int { + return getCookiesState.withLock(\.callCount) + } + public var getCookiesHandler: (@Sendable (Bool) async throws -> ())? { + get { getCookiesState.withLock(\.handler) } + set { getCookiesState.withLock { $0.handler = newValue } } + } + public func getCookies(force: Bool) async throws { + let getCookiesHandler = getCookiesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCookiesHandler = getCookiesHandler { + try await getCookiesHandler(force) + } + + } + + private let getRegistrationFieldsState = MockoloMutex(MockoloHandlerState [PickerFields]>()) + public var getRegistrationFieldsCallCount: Int { + return getRegistrationFieldsState.withLock(\.callCount) + } + public var getRegistrationFieldsHandler: (@Sendable () async throws -> [PickerFields])? { + get { getRegistrationFieldsState.withLock(\.handler) } + set { getRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func getRegistrationFields() async throws -> [PickerFields] { + let getRegistrationFieldsHandler = getRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getRegistrationFieldsHandler = getRegistrationFieldsHandler { + return try await getRegistrationFieldsHandler() + } + return [PickerFields]() + } + + private let registerUserState = MockoloMutex(MockoloHandlerState User>()) + public var registerUserCallCount: Int { + return registerUserState.withLock(\.callCount) + } + public var registerUserHandler: (@Sendable ([String: String], Bool) async throws -> User)? { + get { registerUserState.withLock(\.handler) } + set { registerUserState.withLock { $0.handler = newValue } } + } + public func registerUser(fields: [String: String], isSocial: Bool) async throws -> User { + let registerUserHandler = registerUserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let registerUserHandler = registerUserHandler { + return try await registerUserHandler(fields, isSocial) + } + fatalError("registerUserHandler returns can't have a default value thus its handler must be set") + } + + private let validateRegistrationFieldsState = MockoloMutex(MockoloHandlerState [String: String]>()) + public var validateRegistrationFieldsCallCount: Int { + return validateRegistrationFieldsState.withLock(\.callCount) + } + public var validateRegistrationFieldsHandler: (@Sendable ([String: String]) async throws -> [String: String])? { + get { validateRegistrationFieldsState.withLock(\.handler) } + set { validateRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func validateRegistrationFields(fields: [String: String]) async throws -> [String: String] { + let validateRegistrationFieldsHandler = validateRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let validateRegistrationFieldsHandler = validateRegistrationFieldsHandler { + return try await validateRegistrationFieldsHandler(fields) + } + return [String: String]() + } +} + +public final class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let submitOfflineProgressState = MockoloMutex(MockoloHandlerState Bool>()) + public var submitOfflineProgressCallCount: Int { + return submitOfflineProgressState.withLock(\.callCount) + } + public var submitOfflineProgressHandler: (@Sendable (String, String, String) async throws -> Bool)? { + get { submitOfflineProgressState.withLock(\.handler) } + set { submitOfflineProgressState.withLock { $0.handler = newValue } } + } + public func submitOfflineProgress(courseID: String, blockID: String, data: String) async throws -> Bool { + let submitOfflineProgressHandler = submitOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let submitOfflineProgressHandler = submitOfflineProgressHandler { + return try await submitOfflineProgressHandler(courseID, blockID, data) + } + return false + } +} + +public final class WebviewCookiesUpdateProtocolMock: WebviewCookiesUpdateProtocol { + public init() { } + public init(authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock(), cookiesReady: Bool = false, updatingCookies: Bool = false, errorMessage: String? = nil) { + self.authInteractor = authInteractor + self.cookiesReady = cookiesReady + self.updatingCookies = updatingCookies + self.errorMessage = errorMessage + } + + + + public var authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock() + + public private(set) var cookiesReadySetCallCount = 0 + public var cookiesReady: Bool = false { didSet { cookiesReadySetCallCount += 1 } } + + public private(set) var updatingCookiesSetCallCount = 0 + public var updatingCookies: Bool = false { didSet { updatingCookiesSetCallCount += 1 } } + + public private(set) var errorMessageSetCallCount = 0 + public var errorMessage: String? = nil { didSet { errorMessageSetCallCount += 1 } } + + public private(set) var updateCookiesCallCount = 0 + public var updateCookiesHandler: ((Bool, Int) async -> ())? + public func updateCookies(force: Bool, retryCount: Int) async { + updateCookiesCallCount += 1 + if let updateCookiesHandler = updateCookiesHandler { + await updateCookiesHandler(force, retryCount) + } + + } +} + +public final class BaseRouterMock: BaseRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class CalendarManagerProtocolMock: CalendarManagerProtocol, @unchecked Sendable { + public init() { } + + + private let createCalendarIfNeededState = MockoloMutex(MockoloHandlerState ()>()) + public var createCalendarIfNeededCallCount: Int { + return createCalendarIfNeededState.withLock(\.callCount) + } + public var createCalendarIfNeededHandler: (@Sendable () -> ())? { + get { createCalendarIfNeededState.withLock(\.handler) } + set { createCalendarIfNeededState.withLock { $0.handler = newValue } } + } + public func createCalendarIfNeeded() { + let createCalendarIfNeededHandler = createCalendarIfNeededState.withLock { state in + state.callCount += 1 + return state.handler + } + if let createCalendarIfNeededHandler = createCalendarIfNeededHandler { + createCalendarIfNeededHandler() + } + + } + + private let filterCoursesBySelectedState = MockoloMutex(MockoloHandlerState [CourseForSync]>()) + public var filterCoursesBySelectedCallCount: Int { + return filterCoursesBySelectedState.withLock(\.callCount) + } + public var filterCoursesBySelectedHandler: (@Sendable ([CourseForSync]) async -> [CourseForSync])? { + get { filterCoursesBySelectedState.withLock(\.handler) } + set { filterCoursesBySelectedState.withLock { $0.handler = newValue } } + } + public func filterCoursesBySelected(fetchedCourses: [CourseForSync]) async -> [CourseForSync] { + let filterCoursesBySelectedHandler = filterCoursesBySelectedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let filterCoursesBySelectedHandler = filterCoursesBySelectedHandler { + return await filterCoursesBySelectedHandler(fetchedCourses) + } + return [CourseForSync]() + } + + private let removeOldCalendarState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOldCalendarCallCount: Int { + return removeOldCalendarState.withLock(\.callCount) + } + public var removeOldCalendarHandler: (@Sendable () -> ())? { + get { removeOldCalendarState.withLock(\.handler) } + set { removeOldCalendarState.withLock { $0.handler = newValue } } + } + public func removeOldCalendar() { + let removeOldCalendarHandler = removeOldCalendarState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOldCalendarHandler = removeOldCalendarHandler { + removeOldCalendarHandler() + } + + } + + private let removeOutdatedEventsState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOutdatedEventsCallCount: Int { + return removeOutdatedEventsState.withLock(\.callCount) + } + public var removeOutdatedEventsHandler: (@Sendable (String) async -> ())? { + get { removeOutdatedEventsState.withLock(\.handler) } + set { removeOutdatedEventsState.withLock { $0.handler = newValue } } + } + public func removeOutdatedEvents(courseID: String) async { + let removeOutdatedEventsHandler = removeOutdatedEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOutdatedEventsHandler = removeOutdatedEventsHandler { + await removeOutdatedEventsHandler(courseID) + } + + } + + private let syncCourseState = MockoloMutex(MockoloHandlerState ()>()) + public var syncCourseCallCount: Int { + return syncCourseState.withLock(\.callCount) + } + public var syncCourseHandler: (@Sendable (String, String, CourseDates) async -> ())? { + get { syncCourseState.withLock(\.handler) } + set { syncCourseState.withLock { $0.handler = newValue } } + } + public func syncCourse(courseID: String, courseName: String, dates: CourseDates) async { + let syncCourseHandler = syncCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let syncCourseHandler = syncCourseHandler { + await syncCourseHandler(courseID, courseName, dates) + } + + } + + private let requestAccessState = MockoloMutex(MockoloHandlerState Bool>()) + public var requestAccessCallCount: Int { + return requestAccessState.withLock(\.callCount) + } + public var requestAccessHandler: (@Sendable () async -> Bool)? { + get { requestAccessState.withLock(\.handler) } + set { requestAccessState.withLock { $0.handler = newValue } } + } + public func requestAccess() async -> Bool { + let requestAccessHandler = requestAccessState.withLock { state in + state.callCount += 1 + return state.handler + } + if let requestAccessHandler = requestAccessHandler { + return await requestAccessHandler() + } + return false + } + + private let courseStatusState = MockoloMutex(MockoloHandlerState SyncStatus>()) + public var courseStatusCallCount: Int { + return courseStatusState.withLock(\.callCount) + } + public var courseStatusHandler: (@Sendable (String) async -> SyncStatus)? { + get { courseStatusState.withLock(\.handler) } + set { courseStatusState.withLock { $0.handler = newValue } } + } + public func courseStatus(courseID: String) async -> SyncStatus { + let courseStatusHandler = courseStatusState.withLock { state in + state.callCount += 1 + return state.handler + } + if let courseStatusHandler = courseStatusHandler { + return await courseStatusHandler(courseID) + } + fatalError("courseStatusHandler returns can't have a default value thus its handler must be set") + } + + private let clearAllDataState = MockoloMutex(MockoloHandlerState ()>()) + public var clearAllDataCallCount: Int { + return clearAllDataState.withLock(\.callCount) + } + public var clearAllDataHandler: (@Sendable (Bool) async -> ())? { + get { clearAllDataState.withLock(\.handler) } + set { clearAllDataState.withLock { $0.handler = newValue } } + } + public func clearAllData(removeCalendar: Bool) async { + let clearAllDataHandler = clearAllDataState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearAllDataHandler = clearAllDataHandler { + await clearAllDataHandler(removeCalendar) + } + + } + + private let isDatesChangedState = MockoloMutex(MockoloHandlerState Bool>()) + public var isDatesChangedCallCount: Int { + return isDatesChangedState.withLock(\.callCount) + } + public var isDatesChangedHandler: (@Sendable (String, String) async -> Bool)? { + get { isDatesChangedState.withLock(\.handler) } + set { isDatesChangedState.withLock { $0.handler = newValue } } + } + public func isDatesChanged(courseID: String, checksum: String) async -> Bool { + let isDatesChangedHandler = isDatesChangedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isDatesChangedHandler = isDatesChangedHandler { + return await isDatesChangedHandler(courseID, checksum) + } + return false + } +} + +public final class CorePersistenceProtocolMock: CorePersistenceProtocol, @unchecked Sendable { + public init() { } + + + private let setState = MockoloMutex(MockoloHandlerState ()>()) + public var setCallCount: Int { + return setState.withLock(\.callCount) + } + public var setHandler: (@Sendable (Int) -> ())? { + get { setState.withLock(\.handler) } + set { setState.withLock { $0.handler = newValue } } + } + public func set(userId: Int) { + let setHandler = setState.withLock { state in + state.callCount += 1 + return state.handler + } + if let setHandler = setHandler { + setHandler(userId) + } + + } + + private let getUserIDState = MockoloMutex(MockoloHandlerState Int?>()) + public var getUserIDCallCount: Int { + return getUserIDState.withLock(\.callCount) + } + public var getUserIDHandler: (@Sendable () -> Int?)? { + get { getUserIDState.withLock(\.handler) } + set { getUserIDState.withLock { $0.handler = newValue } } + } + public func getUserID() -> Int? { + let getUserIDHandler = getUserIDState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getUserIDHandler = getUserIDHandler { + return getUserIDHandler() + } + return nil + } + + private let publisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var publisherCallCount: Int { + return publisherState.withLock(\.callCount) + } + public var publisherHandler: (@Sendable () throws -> AnyPublisher)? { + get { publisherState.withLock(\.handler) } + set { publisherState.withLock { $0.handler = newValue } } + } + public func publisher() throws -> AnyPublisher { + let publisherHandler = publisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let publisherHandler = publisherHandler { + return try publisherHandler() + } + fatalError("publisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([DownloadDataTask]) -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(tasks: [DownloadDataTask]) { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + addToDownloadQueueHandler(tasks) + } + + } + + private let saveOfflineProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var saveOfflineProgressCallCount: Int { + return saveOfflineProgressState.withLock(\.callCount) + } + public var saveOfflineProgressHandler: (@Sendable (OfflineProgress) async -> ())? { + get { saveOfflineProgressState.withLock(\.handler) } + set { saveOfflineProgressState.withLock { $0.handler = newValue } } + } + public func saveOfflineProgress(progress: OfflineProgress) async { + let saveOfflineProgressHandler = saveOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveOfflineProgressHandler = saveOfflineProgressHandler { + await saveOfflineProgressHandler(progress) + } + + } + + private let loadProgressState = MockoloMutex(MockoloHandlerState OfflineProgress?>()) + public var loadProgressCallCount: Int { + return loadProgressState.withLock(\.callCount) + } + public var loadProgressHandler: (@Sendable (String) async -> OfflineProgress?)? { + get { loadProgressState.withLock(\.handler) } + set { loadProgressState.withLock { $0.handler = newValue } } + } + public func loadProgress(for blockID: String) async -> OfflineProgress? { + let loadProgressHandler = loadProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadProgressHandler = loadProgressHandler { + return await loadProgressHandler(blockID) + } + return nil + } + + private let loadAllOfflineProgressState = MockoloMutex(MockoloHandlerState [OfflineProgress]>()) + public var loadAllOfflineProgressCallCount: Int { + return loadAllOfflineProgressState.withLock(\.callCount) + } + public var loadAllOfflineProgressHandler: (@Sendable () async -> [OfflineProgress])? { + get { loadAllOfflineProgressState.withLock(\.handler) } + set { loadAllOfflineProgressState.withLock { $0.handler = newValue } } + } + public func loadAllOfflineProgress() async -> [OfflineProgress] { + let loadAllOfflineProgressHandler = loadAllOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadAllOfflineProgressHandler = loadAllOfflineProgressHandler { + return await loadAllOfflineProgressHandler() + } + return [OfflineProgress]() + } + + private let deleteProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteProgressCallCount: Int { + return deleteProgressState.withLock(\.callCount) + } + public var deleteProgressHandler: (@Sendable (String) async -> ())? { + get { deleteProgressState.withLock(\.handler) } + set { deleteProgressState.withLock { $0.handler = newValue } } + } + public func deleteProgress(for blockID: String) async { + let deleteProgressHandler = deleteProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteProgressHandler = deleteProgressHandler { + await deleteProgressHandler(blockID) + } + + } + + private let deleteAllProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllProgressCallCount: Int { + return deleteAllProgressState.withLock(\.callCount) + } + public var deleteAllProgressHandler: (@Sendable () async -> ())? { + get { deleteAllProgressState.withLock(\.handler) } + set { deleteAllProgressState.withLock { $0.handler = newValue } } + } + public func deleteAllProgress() async { + let deleteAllProgressHandler = deleteAllProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllProgressHandler = deleteAllProgressHandler { + await deleteAllProgressHandler() + } + + } + + private let addToDownloadQueueBlocksState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueBlocksCallCount: Int { + return addToDownloadQueueBlocksState.withLock(\.callCount) + } + public var addToDownloadQueueBlocksHandler: (@Sendable ([CourseBlock], DownloadQuality) -> ())? { + get { addToDownloadQueueBlocksState.withLock(\.handler) } + set { addToDownloadQueueBlocksState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { + let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksHandler { + addToDownloadQueueBlocksHandler(blocks, downloadQuality) + } + + } + + private let updateTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var updateTaskCallCount: Int { + return updateTaskState.withLock(\.callCount) + } + public var updateTaskHandler: (@Sendable (DownloadDataTask) -> ())? { + get { updateTaskState.withLock(\.handler) } + set { updateTaskState.withLock { $0.handler = newValue } } + } + public func updateTask(task: DownloadDataTask) { + let updateTaskHandler = updateTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateTaskHandler = updateTaskHandler { + updateTaskHandler(task) + } + + } + + private let downloadDataTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadDataTaskCallCount: Int { + return downloadDataTaskState.withLock(\.callCount) + } + public var downloadDataTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadDataTaskState.withLock(\.handler) } + set { downloadDataTaskState.withLock { $0.handler = newValue } } + } + public func downloadDataTask(for blockId: String) async -> DownloadDataTask? { + let downloadDataTaskHandler = downloadDataTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadDataTaskHandler = downloadDataTaskHandler { + return await downloadDataTaskHandler(blockId) + } + return nil + } + + private let getDownloadDataTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksCallCount: Int { + return getDownloadDataTasksState.withLock(\.callCount) + } + public var getDownloadDataTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadDataTasksState.withLock(\.handler) } + set { getDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasks() async -> [DownloadDataTask] { + let getDownloadDataTasksHandler = getDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksHandler = getDownloadDataTasksHandler { + return await getDownloadDataTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadDataTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksForCourseCallCount: Int { + return getDownloadDataTasksForCourseState.withLock(\.callCount) + } + public var getDownloadDataTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadDataTasksForCourseState.withLock(\.handler) } + set { getDownloadDataTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseHandler { + return await getDownloadDataTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let deleteDownloadDataTasksState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteDownloadDataTasksCallCount: Int { + return deleteDownloadDataTasksState.withLock(\.callCount) + } + public var deleteDownloadDataTasksHandler: (@Sendable ([String]) -> ())? { + get { deleteDownloadDataTasksState.withLock(\.handler) } + set { deleteDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func deleteDownloadDataTasks(ids: [String]) { + let deleteDownloadDataTasksHandler = deleteDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteDownloadDataTasksHandler = deleteDownloadDataTasksHandler { + deleteDownloadDataTasksHandler(ids) + } + + } +} + +public final class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseBlocksCallCount: Int { + return getCourseBlocksState.withLock(\.callCount) + } + public var getCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getCourseBlocksState.withLock(\.handler) } + set { getCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseBlocks(courseID: String) async throws -> CourseStructure { + let getCourseBlocksHandler = getCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseBlocksHandler = getCourseBlocksHandler { + return try await getCourseBlocksHandler(courseID) + } + fatalError("getCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getLoadedCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getLoadedCourseBlocksCallCount: Int { + return getLoadedCourseBlocksState.withLock(\.callCount) + } + public var getLoadedCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getLoadedCourseBlocksState.withLock(\.handler) } + set { getLoadedCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure { + let getLoadedCourseBlocksHandler = getLoadedCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseBlocksHandler = getLoadedCourseBlocksHandler { + return try await getLoadedCourseBlocksHandler(courseID) + } + fatalError("getLoadedCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let shiftDueDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var shiftDueDatesCallCount: Int { + return shiftDueDatesState.withLock(\.callCount) + } + public var shiftDueDatesHandler: (@Sendable (String) async throws -> ())? { + get { shiftDueDatesState.withLock(\.handler) } + set { shiftDueDatesState.withLock { $0.handler = newValue } } + } + public func shiftDueDates(courseID: String) async throws { + let shiftDueDatesHandler = shiftDueDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let shiftDueDatesHandler = shiftDueDatesHandler { + try await shiftDueDatesHandler(courseID) + } + + } +} + +public final class AuthorizationRouterMock: AuthorizationRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let showUpdateRequiredViewState = MockoloMutex(MockoloHandlerState ()>()) + public var showUpdateRequiredViewCallCount: Int { + return showUpdateRequiredViewState.withLock(\.callCount) + } + public var showUpdateRequiredViewHandler: (@Sendable (Bool) -> ())? { + get { showUpdateRequiredViewState.withLock(\.handler) } + set { showUpdateRequiredViewState.withLock { $0.handler = newValue } } + } + public func showUpdateRequiredView(showAccountLink: Bool) { + let showUpdateRequiredViewHandler = showUpdateRequiredViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showUpdateRequiredViewHandler = showUpdateRequiredViewHandler { + showUpdateRequiredViewHandler(showAccountLink) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class ConnectivityProtocolMock: ConnectivityProtocol, @unchecked Sendable { + public init() { } + public init(isInternetAvaliable: Bool = false, isMobileData: Bool = false) { + self.isInternetAvaliable = isInternetAvaliable + self.isMobileData = isMobileData + } + + + + public var isInternetAvaliable: Bool = false + + + public var isMobileData: Bool = false + + + private var _internetReachableSubject: CurrentValueSubject! + public var internetReachableSubject: CurrentValueSubject { + get { return _internetReachableSubject } + set { _internetReachableSubject = newValue } + } +} + +public final class AuthorizationAnalyticsMock: AuthorizationAnalytics { + public init() { } + + + public private(set) var identifyCallCount = 0 + public var identifyHandler: ((String, String, String) -> ())? + public func identify(id: String, username: String, email: String) { + identifyCallCount += 1 + if let identifyHandler = identifyHandler { + identifyHandler(id, username, email) + } + + } + + public private(set) var userLoginCallCount = 0 + public var userLoginHandler: ((AuthMethod) -> ())? + public func userLogin(method: AuthMethod) { + userLoginCallCount += 1 + if let userLoginHandler = userLoginHandler { + userLoginHandler(method) + } + + } + + public private(set) var registerClickedCallCount = 0 + public var registerClickedHandler: (() -> ())? + public func registerClicked() { + registerClickedCallCount += 1 + if let registerClickedHandler = registerClickedHandler { + registerClickedHandler() + } + + } + + public private(set) var signInClickedCallCount = 0 + public var signInClickedHandler: (() -> ())? + public func signInClicked() { + signInClickedCallCount += 1 + if let signInClickedHandler = signInClickedHandler { + signInClickedHandler() + } + + } + + public private(set) var userSignInClickedCallCount = 0 + public var userSignInClickedHandler: (() -> ())? + public func userSignInClicked() { + userSignInClickedCallCount += 1 + if let userSignInClickedHandler = userSignInClickedHandler { + userSignInClickedHandler() + } + + } + + public private(set) var createAccountClickedCallCount = 0 + public var createAccountClickedHandler: (() -> ())? + public func createAccountClicked() { + createAccountClickedCallCount += 1 + if let createAccountClickedHandler = createAccountClickedHandler { + createAccountClickedHandler() + } + + } + + public private(set) var registrationSuccessCallCount = 0 + public var registrationSuccessHandler: ((String) -> ())? + public func registrationSuccess(method: String) { + registrationSuccessCallCount += 1 + if let registrationSuccessHandler = registrationSuccessHandler { + registrationSuccessHandler(method) + } + + } + + public private(set) var forgotPasswordClickedCallCount = 0 + public var forgotPasswordClickedHandler: (() -> ())? + public func forgotPasswordClicked() { + forgotPasswordClickedCallCount += 1 + if let forgotPasswordClickedHandler = forgotPasswordClickedHandler { + forgotPasswordClickedHandler() + } + + } + + public private(set) var resetPasswordClickedCallCount = 0 + public var resetPasswordClickedHandler: (() -> ())? + public func resetPasswordClicked() { + resetPasswordClickedCallCount += 1 + if let resetPasswordClickedHandler = resetPasswordClickedHandler { + resetPasswordClickedHandler() + } + + } + + public private(set) var resetPasswordCallCount = 0 + public var resetPasswordHandler: ((Bool) -> ())? + public func resetPassword(success: Bool) { + resetPasswordCallCount += 1 + if let resetPasswordHandler = resetPasswordHandler { + resetPasswordHandler(success) + } + + } + + public private(set) var authTrackScreenEventCallCount = 0 + public var authTrackScreenEventHandler: ((AnalyticsEvent, EventBIValue) -> ())? + public func authTrackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { + authTrackScreenEventCallCount += 1 + if let authTrackScreenEventHandler = authTrackScreenEventHandler { + authTrackScreenEventHandler(event, biValue) + } + + } +} + +public final class DownloadManagerProtocolMock: DownloadManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCurrentDownloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var getCurrentDownloadTaskCallCount: Int { + return getCurrentDownloadTaskState.withLock(\.callCount) + } + public var getCurrentDownloadTaskHandler: (@Sendable () async -> DownloadDataTask?)? { + get { getCurrentDownloadTaskState.withLock(\.handler) } + set { getCurrentDownloadTaskState.withLock { $0.handler = newValue } } + } + public func getCurrentDownloadTask() async -> DownloadDataTask? { + let getCurrentDownloadTaskHandler = getCurrentDownloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCurrentDownloadTaskHandler = getCurrentDownloadTaskHandler { + return await getCurrentDownloadTaskHandler() + } + return nil + } + + private let eventPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var eventPublisherCallCount: Int { + return eventPublisherState.withLock(\.callCount) + } + public var eventPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { eventPublisherState.withLock(\.handler) } + set { eventPublisherState.withLock { $0.handler = newValue } } + } + public func eventPublisher() -> AnyPublisher { + let eventPublisherHandler = eventPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let eventPublisherHandler = eventPublisherHandler { + return eventPublisherHandler() + } + fatalError("eventPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([CourseBlock]) async throws -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock]) async throws { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + try await addToDownloadQueueHandler(blocks) + } + + } + + private let getDownloadTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksCallCount: Int { + return getDownloadTasksState.withLock(\.callCount) + } + public var getDownloadTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadTasksState.withLock(\.handler) } + set { getDownloadTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadTasks() async -> [DownloadDataTask] { + let getDownloadTasksHandler = getDownloadTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksHandler = getDownloadTasksHandler { + return await getDownloadTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksForCourseCallCount: Int { + return getDownloadTasksForCourseState.withLock(\.callCount) + } + public var getDownloadTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadTasksForCourseState.withLock(\.handler) } + set { getDownloadTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadTasksForCourseHandler = getDownloadTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksForCourseHandler = getDownloadTasksForCourseHandler { + return await getDownloadTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let cancelDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCallCount: Int { + return cancelDownloadingState.withLock(\.callCount) + } + public var cancelDownloadingHandler: (@Sendable (String, [CourseBlock]) async throws -> ())? { + get { cancelDownloadingState.withLock(\.handler) } + set { cancelDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String, blocks: [CourseBlock]) async throws { + let cancelDownloadingHandler = cancelDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingHandler = cancelDownloadingHandler { + try await cancelDownloadingHandler(courseId, blocks) + } + + } + + private let cancelDownloadingTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingTaskCallCount: Int { + return cancelDownloadingTaskState.withLock(\.callCount) + } + public var cancelDownloadingTaskHandler: (@Sendable (DownloadDataTask) async throws -> ())? { + get { cancelDownloadingTaskState.withLock(\.handler) } + set { cancelDownloadingTaskState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(task: DownloadDataTask) async throws { + let cancelDownloadingTaskHandler = cancelDownloadingTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingTaskHandler = cancelDownloadingTaskHandler { + try await cancelDownloadingTaskHandler(task) + } + + } + + private let cancelDownloadingCourseIdState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCourseIdCallCount: Int { + return cancelDownloadingCourseIdState.withLock(\.callCount) + } + public var cancelDownloadingCourseIdHandler: (@Sendable (String) async throws -> ())? { + get { cancelDownloadingCourseIdState.withLock(\.handler) } + set { cancelDownloadingCourseIdState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String) async throws { + let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdHandler { + try await cancelDownloadingCourseIdHandler(courseId) + } + + } + + private let cancelAllDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelAllDownloadingCallCount: Int { + return cancelAllDownloadingState.withLock(\.callCount) + } + public var cancelAllDownloadingHandler: (@Sendable () async throws -> ())? { + get { cancelAllDownloadingState.withLock(\.handler) } + set { cancelAllDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelAllDownloading() async throws { + let cancelAllDownloadingHandler = cancelAllDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelAllDownloadingHandler = cancelAllDownloadingHandler { + try await cancelAllDownloadingHandler() + } + + } + + private let deleteAllState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllCallCount: Int { + return deleteAllState.withLock(\.callCount) + } + public var deleteAllHandler: (@Sendable () async -> ())? { + get { deleteAllState.withLock(\.handler) } + set { deleteAllState.withLock { $0.handler = newValue } } + } + public func deleteAll() async { + let deleteAllHandler = deleteAllState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllHandler = deleteAllHandler { + await deleteAllHandler() + } + + } + + private let fileUrlState = MockoloMutex(MockoloHandlerState URL?>()) + public var fileUrlCallCount: Int { + return fileUrlState.withLock(\.callCount) + } + public var fileUrlHandler: (@Sendable (String) async -> URL?)? { + get { fileUrlState.withLock(\.handler) } + set { fileUrlState.withLock { $0.handler = newValue } } + } + public func fileUrl(for blockId: String) async -> URL? { + let fileUrlHandler = fileUrlState.withLock { state in + state.callCount += 1 + return state.handler + } + if let fileUrlHandler = fileUrlHandler { + return await fileUrlHandler(blockId) + } + return nil + } + + private let resumeDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var resumeDownloadingCallCount: Int { + return resumeDownloadingState.withLock(\.callCount) + } + public var resumeDownloadingHandler: (@Sendable () async throws -> ())? { + get { resumeDownloadingState.withLock(\.handler) } + set { resumeDownloadingState.withLock { $0.handler = newValue } } + } + public func resumeDownloading() async throws { + let resumeDownloadingHandler = resumeDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resumeDownloadingHandler = resumeDownloadingHandler { + try await resumeDownloadingHandler() + } + + } + + private let isLargeVideosSizeState = MockoloMutex(MockoloHandlerState Bool>()) + public var isLargeVideosSizeCallCount: Int { + return isLargeVideosSizeState.withLock(\.callCount) + } + public var isLargeVideosSizeHandler: (@Sendable ([CourseBlock]) async -> Bool)? { + get { isLargeVideosSizeState.withLock(\.handler) } + set { isLargeVideosSizeState.withLock { $0.handler = newValue } } + } + public func isLargeVideosSize(blocks: [CourseBlock]) async -> Bool { + let isLargeVideosSizeHandler = isLargeVideosSizeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isLargeVideosSizeHandler = isLargeVideosSizeHandler { + return await isLargeVideosSizeHandler(blocks) + } + return false + } + + private let removeAppSupportDirectoryUnusedContentState = MockoloMutex(MockoloHandlerState ()>()) + public var removeAppSupportDirectoryUnusedContentCallCount: Int { + return removeAppSupportDirectoryUnusedContentState.withLock(\.callCount) + } + public var removeAppSupportDirectoryUnusedContentHandler: (@Sendable () -> ())? { + get { removeAppSupportDirectoryUnusedContentState.withLock(\.handler) } + set { removeAppSupportDirectoryUnusedContentState.withLock { $0.handler = newValue } } + } + public func removeAppSupportDirectoryUnusedContent() { + let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentHandler { + removeAppSupportDirectoryUnusedContentHandler() + } + + } + + private let deleteState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteCallCount: Int { + return deleteState.withLock(\.callCount) + } + public var deleteHandler: (@Sendable ([CourseBlock], String) async -> ())? { + get { deleteState.withLock(\.handler) } + set { deleteState.withLock { $0.handler = newValue } } + } + public func delete(blocks: [CourseBlock], courseId: String) async { + let deleteHandler = deleteState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteHandler = deleteHandler { + await deleteHandler(blocks, courseId) + } + + } + + private let downloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadTaskCallCount: Int { + return downloadTaskState.withLock(\.callCount) + } + public var downloadTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadTaskState.withLock(\.handler) } + set { downloadTaskState.withLock { $0.handler = newValue } } + } + public func downloadTask(for blockId: String) async -> DownloadDataTask? { + let downloadTaskHandler = downloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadTaskHandler = downloadTaskHandler { + return await downloadTaskHandler(blockId) + } + return nil + } + + private let getFreeDiskSpaceState = MockoloMutex(MockoloHandlerState Int?>()) + public var getFreeDiskSpaceCallCount: Int { + return getFreeDiskSpaceState.withLock(\.callCount) + } + public var getFreeDiskSpaceHandler: (@Sendable () -> Int?)? { + get { getFreeDiskSpaceState.withLock(\.handler) } + set { getFreeDiskSpaceState.withLock { $0.handler = newValue } } + } + public func getFreeDiskSpace() -> Int? { + let getFreeDiskSpaceHandler = getFreeDiskSpaceState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getFreeDiskSpaceHandler = getFreeDiskSpaceHandler { + return getFreeDiskSpaceHandler() + } + return nil + } +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { + print("At \(function), the captured arguments are not Sendable, it is not concurrency-safe.") +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { +} + +/// Will be replaced to `Synchronization.Mutex` in future. +fileprivate final class MockoloMutex: @unchecked Sendable { + private let lock = NSLock() + private var value: Value + init(_ initialValue: Value) { + self.value = initialValue + } +#if compiler(>=6.0) + borrowing func withLock(_ body: (inout sending Value) throws(E) -> Result) throws(E) -> sending Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#else + func withLock(_ body: (inout Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#endif +} + +fileprivate struct MockoloUnsafeTransfer: @unchecked Sendable { + var value: Value + init(_ value: Value) { + self.value = value + } +} + +fileprivate struct MockoloHandlerState { + var argValues: [MockoloUnsafeTransfer] = [] + var handler: Handler? = nil + var callCount: Int = 0 +} + diff --git a/Authorization/AuthorizationTests/Presentation/Login/ResetPasswordViewModelTests.swift b/Authorization/AuthorizationTests/Presentation/Login/ResetPasswordViewModelTests.swift index 52c85a357..8ac2bf436 100644 --- a/Authorization/AuthorizationTests/Presentation/Login/ResetPasswordViewModelTests.swift +++ b/Authorization/AuthorizationTests/Presentation/Login/ResetPasswordViewModelTests.swift @@ -2,10 +2,9 @@ // ResetPasswordViewModelTests.swift // AuthorizationTests // -// Created by  Stepanok Ivan on 04.04.2023. +// Created by Stepanok Ivan on 04.04.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Authorization @@ -25,7 +24,7 @@ final class ResetPasswordViewModelTests: XCTestCase { router: router, analytics: analytics, validator: validator) - + var isRecoveryPassword = true let binding = Binding(get: { return isRecoveryPassword @@ -35,13 +34,13 @@ final class ResetPasswordViewModelTests: XCTestCase { await viewModel.resetPassword(email: "e", isRecovered: binding) - Verify(interactor, 0, .resetPassword(email: .any)) + XCTAssertEqual(interactor.resetPasswordCallCount, 0) XCTAssertEqual(viewModel.errorMessage, AuthLocalization.Error.invalidEmailAddress) XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(isRecoveryPassword, true) } - + func testResetPasswordSuccess() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -58,20 +57,20 @@ final class ResetPasswordViewModelTests: XCTestCase { }, set: { value in isRecoveryPassword = value }) - + let data = ResetPassword(success: true, responseText: "Success") - Given(interactor, .resetPassword(email: .any, willReturn: data)) + interactor.resetPasswordHandler = { _ in data } await viewModel.resetPassword(email: "edxUser@edx.com", isRecovered: binding) - Verify(interactor, 1, .resetPassword(email: .any)) + XCTAssertEqual(interactor.resetPasswordCallCount, 1) XCTAssertFalse(isRecoveryPassword) XCTAssertEqual(viewModel.errorMessage, nil) XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(isRecoveryPassword, false) } - + func testResetPasswordErrorValidation() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -86,7 +85,7 @@ final class ResetPasswordViewModelTests: XCTestCase { let validationError = CustomValidationError(statusCode: 400, data: ["value": validationErrorMessage]) let error = AFError.responseValidationFailed(reason: AFError.ResponseValidationFailureReason.customValidationFailed(error: validationError)) - Given(interactor, .resetPassword(email: .any, willThrow: error)) + interactor.resetPasswordHandler = { _ in throw error } var isRecoveryPassword = true let binding = Binding(get: { @@ -97,13 +96,13 @@ final class ResetPasswordViewModelTests: XCTestCase { await viewModel.resetPassword(email: "edxUser@edx.com", isRecovered: binding) - Verify(interactor, 1, .resetPassword(email: .any)) + XCTAssertEqual(interactor.resetPasswordCallCount, 1) XCTAssertEqual(viewModel.errorMessage, validationErrorMessage) XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(isRecoveryPassword, true) } - + func testResetPasswordErrorInvalidGrant() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -114,7 +113,7 @@ final class ResetPasswordViewModelTests: XCTestCase { analytics: analytics, validator: validator) - Given(interactor, .resetPassword(email: .any, willThrow: APIError.invalidGrant)) + interactor.resetPasswordHandler = { _ in throw APIError.invalidGrant } var isRecoveryPassword = true let binding = Binding(get: { @@ -125,13 +124,13 @@ final class ResetPasswordViewModelTests: XCTestCase { await viewModel.resetPassword(email: "edxUser@edx.com", isRecovered: binding) - Verify(interactor, 1, .resetPassword(email: .any)) + XCTAssertEqual(interactor.resetPasswordCallCount, 1) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.invalidCredentials) XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(isRecoveryPassword, true) } - + func testResetPasswordErrorUnknown() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -142,7 +141,7 @@ final class ResetPasswordViewModelTests: XCTestCase { analytics: analytics, validator: validator) - Given(interactor, .resetPassword(email: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) + interactor.resetPasswordHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } var isRecoveryPassword = true let binding = Binding(get: { @@ -153,13 +152,13 @@ final class ResetPasswordViewModelTests: XCTestCase { await viewModel.resetPassword(email: "edxUser@edx.com", isRecovered: binding) - Verify(interactor, 1, .resetPassword(email: .any)) + XCTAssertEqual(interactor.resetPasswordCallCount, 1) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(isRecoveryPassword, true) } - + func testResetPasswordNoInternetError() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -172,7 +171,7 @@ final class ResetPasswordViewModelTests: XCTestCase { let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - Given(interactor, .resetPassword(email: .any, willThrow: noInternetError)) + interactor.resetPasswordHandler = { _ in throw noInternetError } var isRecoveryPassword = true let binding = Binding(get: { @@ -183,7 +182,7 @@ final class ResetPasswordViewModelTests: XCTestCase { await viewModel.resetPassword(email: "edxUser@edx.com", isRecovered: binding) - Verify(interactor, 1, .resetPassword(email: .any)) + XCTAssertEqual(interactor.resetPasswordCallCount, 1) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertEqual(viewModel.isShowProgress, false) diff --git a/Authorization/AuthorizationTests/Presentation/Login/SignInViewModelTests.swift b/Authorization/AuthorizationTests/Presentation/Login/SignInViewModelTests.swift index f5bed4ac6..324a5d748 100644 --- a/Authorization/AuthorizationTests/Presentation/Login/SignInViewModelTests.swift +++ b/Authorization/AuthorizationTests/Presentation/Login/SignInViewModelTests.swift @@ -5,7 +5,6 @@ // Created by Vladimir Chekyrta on 10.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Authorization @@ -15,15 +14,15 @@ import SwiftUI @MainActor final class SignInViewModelTests: XCTestCase { - + override func setUpWithError() throws { // Put setup code here. This method is called before the invocation of each test method in the class. } - + override func tearDownWithError() throws { // Put teardown code here. This method is called after the invocation of each test method in the class. } - + func testLoginValidationEmailError() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -31,23 +30,23 @@ final class SignInViewModelTests: XCTestCase { let analytics = AuthorizationAnalyticsMock() let viewModel = SignInViewModel( interactor: interactor, - router: router, + router: router, config: ConfigMock(), analytics: analytics, validator: validator, storage: CoreStorageMock(), sourceScreen: .default ) - + await viewModel.login(username: "", password: "") - - Verify(interactor, 0, .login(username: .any, password: .any)) - Verify(router, 0, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.loginCallCount, 0) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 0) + XCTAssertEqual(viewModel.errorMessage, AuthLocalization.Error.invalidEmailAddressOrUsername) XCTAssertEqual(viewModel.isShowProgress, false) } - + func testLoginValidationPasswordError() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -63,14 +62,14 @@ final class SignInViewModelTests: XCTestCase { sourceScreen: .default ) await viewModel.login(username: "edxUser@edx.com", password: "") - - Verify(interactor, 0, .login(username: .any, password: .any)) - Verify(router, 0, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.loginCallCount, 0) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 0) + XCTAssertEqual(viewModel.errorMessage, AuthLocalization.Error.invalidPasswordLenght) XCTAssertEqual(viewModel.isShowProgress, false) } - + func testLoginSuccess() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -86,19 +85,19 @@ final class SignInViewModelTests: XCTestCase { sourceScreen: .default ) let user = User(id: 1, username: "username", email: "edxUser@edx.com", name: "Name", userAvatar: "") - - Given(interactor, .login(username: .any, password: .any, willReturn: user)) - + + interactor.loginHandler = { _, _ in user } + await viewModel.login(username: "edxUser@edx.com", password: "password123") - - Verify(interactor, 1, .login(username: .any, password: .any)) - Verify(analytics, .userLogin(method: .any)) - Verify(router, 1, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.loginCallCount, 1) + XCTAssertEqual(analytics.userLoginCallCount, 1) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 1) + XCTAssertEqual(viewModel.errorMessage, nil) XCTAssertEqual(viewModel.isShowProgress, true) } - + func testSSOLoginSuccess() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -114,18 +113,18 @@ final class SignInViewModelTests: XCTestCase { sourceScreen: .default ) let user = User(id: 1, username: "username", email: "edxUser@edx.com", name: "Name", userAvatar: "") - - Given(interactor, .login(ssoToken: .any, willReturn: user)) - + + interactor.loginSsoTokenHandler = { _ in user } + await viewModel.ssoLogin(title: "Riyadah") - - Verify(interactor, 1, .login(ssoToken: .any)) - Verify(router, 1, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.loginSsoTokenCallCount, 1) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 1) + XCTAssertEqual(viewModel.errorMessage, nil) XCTAssertEqual(viewModel.isShowProgress, true) } - + func testSocialLoginSuccess() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -146,13 +145,13 @@ final class SignInViewModelTests: XCTestCase { ) let user = User(id: 1, username: "username", email: "edxUser@edx.com", name: "Name", userAvatar: "") - Given(interactor, .login(externalToken: .any, backend: .any, willReturn: user)) + interactor.loginExternalTokenHandler = { _, _ in user } await viewModel.login(with: result) - Verify(interactor, 1, .login(externalToken: .any, backend: .any)) - Verify(analytics, .userLogin(method: .any)) - Verify(router, 1, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) + XCTAssertEqual(interactor.loginExternalTokenCallCount, 1) + XCTAssertEqual(analytics.userLoginCallCount, 1) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 1) XCTAssertEqual(viewModel.errorMessage, nil) XCTAssertEqual(viewModel.isShowProgress, true) @@ -183,12 +182,12 @@ final class SignInViewModelTests: XCTestCase { let validationError = CustomValidationError(statusCode: 400, data: ["error_description": validationErrorMessage]) let error = AFError.responseValidationFailed(reason: AFError.ResponseValidationFailureReason.customValidationFailed(error: validationError)) - Given(interactor, .login(externalToken: .any, backend: .any, willThrow: error)) + interactor.loginExternalTokenHandler = { _, _ in throw error } await viewModel.login(with: result) - Verify(interactor, 1, .login(externalToken: .any, backend: .any)) - Verify(router, 0, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) + XCTAssertEqual(interactor.loginExternalTokenCallCount, 1) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 0) XCTAssertEqual(viewModel.errorMessage, validationErrorMessage) XCTAssertEqual(viewModel.isShowProgress, false) @@ -208,18 +207,18 @@ final class SignInViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - + let validationErrorMessage = "Some error" let validationError = CustomValidationError(statusCode: 400, data: ["error_description": validationErrorMessage]) let error = AFError.responseValidationFailed(reason: AFError.ResponseValidationFailureReason.customValidationFailed(error: validationError)) - - Given(interactor, .login(username: .any, password: .any, willThrow: error)) - + + interactor.loginHandler = { _, _ in throw error } + await viewModel.login(username: "edxUser@edx.com", password: "password123") - - Verify(interactor, 1, .login(username: .any, password: .any)) - Verify(router, 0, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.loginCallCount, 1) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 0) + XCTAssertEqual(viewModel.errorMessage, validationErrorMessage) XCTAssertEqual(viewModel.isShowProgress, false) } @@ -238,18 +237,18 @@ final class SignInViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - - Given(interactor, .login(username: .any, password: .any, willThrow: APIError.invalidGrant)) - + + interactor.loginHandler = { _, _ in throw APIError.invalidGrant } + await viewModel.login(username: "edxUser@edx.com", password: "password123") - - Verify(interactor, 1, .login(username: .any, password: .any)) - Verify(router, 0, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.loginCallCount, 1) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 0) + XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.invalidCredentials) XCTAssertEqual(viewModel.isShowProgress, false) } - + func testLoginErrorUnknown() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -264,18 +263,18 @@ final class SignInViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - - Given(interactor, .login(username: .any, password: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + + interactor.loginHandler = { _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + await viewModel.login(username: "edxUser@edx.com", password: "password123") - - Verify(interactor, 1, .login(username: .any, password: .any)) - Verify(router, 0, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.loginCallCount, 1) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 0) + XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertEqual(viewModel.isShowProgress, false) } - + func testLoginNoInternetError() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -290,20 +289,20 @@ final class SignInViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .login(username: .any, password: .any, willThrow: noInternetError)) - + + interactor.loginHandler = { _, _ in throw noInternetError } + await viewModel.login(username: "edxUser@edx.com", password: "password123") - - Verify(interactor, 1, .login(username: .any, password: .any)) - Verify(router, 0, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.loginCallCount, 1) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 0) + XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertEqual(viewModel.isShowProgress, false) } - + func testTrackForgotPasswordClicked() { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -318,10 +317,10 @@ final class SignInViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - + viewModel.trackForgotPasswordClicked() - - Verify(analytics, 1, .forgotPasswordClicked()) + + XCTAssertEqual(analytics.forgotPasswordClickedCallCount, 1) } - + } diff --git a/Authorization/AuthorizationTests/Presentation/Register/SignUpViewModelTests.swift b/Authorization/AuthorizationTests/Presentation/Register/SignUpViewModelTests.swift index e2a2214bd..dedd4629c 100644 --- a/Authorization/AuthorizationTests/Presentation/Register/SignUpViewModelTests.swift +++ b/Authorization/AuthorizationTests/Presentation/Register/SignUpViewModelTests.swift @@ -2,10 +2,9 @@ // RegisterViewModelTests.swift // AuthorizationTests // -// Created by  Stepanok Ivan on 15.01.2023. +// Created by Stepanok Ivan on 15.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Authorization @@ -15,15 +14,15 @@ import SwiftUI @MainActor final class SignUpViewModelTests: XCTestCase { - + override func setUpWithError() throws { // Put setup code here. This method is called before the invocation of each test method in the class. } - + override func tearDownWithError() throws { // Put teardown code here. This method is called after the invocation of each test method in the class. } - + func testGetRegistrationFieldsSuccess() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -39,24 +38,24 @@ final class SignUpViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - + let fields = [ PickerFields(type: .email, label: "", required: true, name: "email", instructions: "", options: []), PickerFields(type: .password, label: "", required: true, name: "password", instructions: "", options: []), PickerFields(type: .plaintext, label: "", required: true, name: "name", instructions: "", options: []) ] - - Given(interactor, .getRegistrationFields(willReturn: fields)) - + + interactor.getRegistrationFieldsHandler = { fields } + await viewModel.getRegistrationFields() - - Verify(interactor, 1, .getRegistrationFields()) + + XCTAssertEqual(interactor.getRegistrationFieldsCallCount, 1) XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(viewModel.showError, false) XCTAssertEqual(viewModel.errorMessage, nil) - + } - + func testGetRegistrationFieldsNoInternetError() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -72,19 +71,19 @@ final class SignUpViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .getRegistrationFields(willThrow: noInternetError)) - + + interactor.getRegistrationFieldsHandler = { throw noInternetError } + await viewModel.getRegistrationFields() - - Verify(interactor, 1, .getRegistrationFields()) + + XCTAssertEqual(interactor.getRegistrationFieldsCallCount, 1) XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(viewModel.showError, true) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) } - + func testGetRegistrationFieldsUnknownError() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -100,17 +99,17 @@ final class SignUpViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - - Given(interactor, .getRegistrationFields(willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + + interactor.getRegistrationFieldsHandler = { throw NSError(domain: "error", code: -1, userInfo: nil) } + await viewModel.getRegistrationFields() - - Verify(interactor, 1, .getRegistrationFields()) + + XCTAssertEqual(interactor.getRegistrationFieldsCallCount, 1) XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(viewModel.showError, true) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) } - + func testRegisterUserSuccess() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -126,24 +125,22 @@ final class SignUpViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - - Given(interactor, .registerUser(fields: .any, isSocial: .any, willReturn: .init(id: 1, - username: "Name", - email: "mail", - name: "name", - userAvatar: "avatar"))) - Given(interactor, .validateRegistrationFields(fields: .any, willReturn: [:])) - + + interactor.registerUserHandler = { _, _ in + User(id: 1, username: "Name", email: "mail", name: "name", userAvatar: "avatar") + } + interactor.validateRegistrationFieldsHandler = { _ in [:] } + await viewModel.registerUser() - - Verify(interactor, 1, .validateRegistrationFields(fields: .any)) - Verify(interactor, 1, .registerUser(fields: .any, isSocial: .any)) - Verify(router, 1, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.validateRegistrationFieldsCallCount, 1) + XCTAssertEqual(interactor.registerUserCallCount, 1) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 1) + XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(viewModel.showError, false) } - + func testRegisterUserValidationFailure() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -159,7 +156,7 @@ final class SignUpViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - + viewModel.fields = [ FieldConfiguration(field: .init(type: .email, label: "email", @@ -168,21 +165,20 @@ final class SignUpViewModelTests: XCTestCase { instructions: "", options: [])) ] - - Given(interactor, .validateRegistrationFields(fields: .any, willReturn: ["email": "invalid email"])) - Given(interactor, .registerUser(fields: .any, isSocial: .any, willProduce: {_ in})) + + interactor.validateRegistrationFieldsHandler = { _ in ["email": "invalid email"] } await viewModel.registerUser() - - Verify(interactor, 1, .validateRegistrationFields(fields: .any)) - Verify(interactor, 0, .registerUser(fields: .any, isSocial: .any)) - Verify(router, 0, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.validateRegistrationFieldsCallCount, 1) + XCTAssertEqual(interactor.registerUserCallCount, 0) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 0) + XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(viewModel.showError, false) XCTAssertFalse(viewModel.fields.first!.error.isEmpty) } - + func testRegisterUserInvalidCredentials() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -198,21 +194,21 @@ final class SignUpViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - - Given(interactor, .validateRegistrationFields(fields: .any, willReturn: [:])) - Given(interactor, .registerUser(fields: .any, isSocial: .any, willThrow: APIError.invalidGrant)) + + interactor.validateRegistrationFieldsHandler = { _ in [:] } + interactor.registerUserHandler = { _, _ in throw APIError.invalidGrant } await viewModel.registerUser() - - Verify(interactor, 1, .validateRegistrationFields(fields: .any)) - Verify(interactor, 1, .registerUser(fields: .any, isSocial: .any)) - Verify(router, 0, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.validateRegistrationFieldsCallCount, 1) + XCTAssertEqual(interactor.registerUserCallCount, 1) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 0) + XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(viewModel.showError, true) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.invalidCredentials) } - + func testRegisterUserUnknownError() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -228,21 +224,21 @@ final class SignUpViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - - Given(interactor, .validateRegistrationFields(fields: .any, willReturn: [:])) - Given(interactor, .registerUser(fields: .any, isSocial: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) + + interactor.validateRegistrationFieldsHandler = { _ in [:] } + interactor.registerUserHandler = { _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } await viewModel.registerUser() - - Verify(interactor, 1, .validateRegistrationFields(fields: .any)) - Verify(interactor, 1, .registerUser(fields: .any, isSocial: .any)) - Verify(router, 0, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.validateRegistrationFieldsCallCount, 1) + XCTAssertEqual(interactor.registerUserCallCount, 1) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 0) + XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(viewModel.showError, true) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) } - + func testRegisterUserNoInternetError() async throws { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -258,23 +254,23 @@ final class SignUpViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .registerUser(fields: .any, isSocial: .any, willThrow: noInternetError)) - Given(interactor, .validateRegistrationFields(fields: .any, willReturn: [:])) - + + interactor.registerUserHandler = { _, _ in throw noInternetError } + interactor.validateRegistrationFieldsHandler = { _ in [:] } + await viewModel.registerUser() - - Verify(interactor, 1, .validateRegistrationFields(fields: .any)) - Verify(interactor, 1, .registerUser(fields: .any, isSocial: .any)) - Verify(router, 0, .showMainOrWhatsNewScreen(sourceScreen: .any, postLoginData: .any)) - + + XCTAssertEqual(interactor.validateRegistrationFieldsCallCount, 1) + XCTAssertEqual(interactor.registerUserCallCount, 1) + XCTAssertEqual(router.showMainOrWhatsNewScreenCallCount, 0) + XCTAssertEqual(viewModel.isShowProgress, false) XCTAssertEqual(viewModel.showError, true) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) } - + func testTrackCreateAccountClicked() { let interactor = AuthInteractorProtocolMock() let router = AuthorizationRouterMock() @@ -290,9 +286,9 @@ final class SignUpViewModelTests: XCTestCase { storage: CoreStorageMock(), sourceScreen: .default ) - + viewModel.trackCreateAccountClicked() - - Verify(analytics, 1, .createAccountClicked()) + + XCTAssertEqual(analytics.createAccountClickedCallCount, 1) } } diff --git a/Authorization/AuthorizationTests/Presentation/Registersd/RegisterViewModelTests.swift b/Authorization/AuthorizationTests/Presentation/Registersd/RegisterViewModelTests.swift deleted file mode 100644 index 186e3669c..000000000 --- a/Authorization/AuthorizationTests/Presentation/Registersd/RegisterViewModelTests.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// RegisterViewModelTests.swift -// AuthorizationTests -// -// Created by  Stepanok Ivan on 15.01.2023. -// - -import XCTest - -final class RegisterViewModelTests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - // Any test you write for XCTest can be annotated as throws and async. - // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. - // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. - } - - func testPerformanceExample() throws { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } - -} diff --git a/Authorization/Mockfile b/Authorization/Mockfile deleted file mode 100644 index a3ae4b4f7..000000000 --- a/Authorization/Mockfile +++ /dev/null @@ -1,18 +0,0 @@ -sourceryCommand: mint run krzysztofzablocki/Sourcery@2.1.2 sourcery -sourceryTemplate: ../MockTemplate.swifttemplate -unit.tests.mock: - sources: - include: - - ./../Core - - ./Authorization - exclude: [] - output: ./AuthorizationTests/AuthorizationMock.generated.swift - targets: - - MyAppUnitTests - import: - - Core - - Authorization - - Foundation - - SwiftUI - - Combine - - OEXFoundation \ No newline at end of file diff --git a/Core/Core.xcodeproj/project.pbxproj b/Core/Core.xcodeproj/project.pbxproj index d9f070527..0b33f2da7 100644 --- a/Core/Core.xcodeproj/project.pbxproj +++ b/Core/Core.xcodeproj/project.pbxproj @@ -157,7 +157,7 @@ CE54C2D22CC80D8500E529F9 /* DownloadManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE54C2D12CC80D8500E529F9 /* DownloadManagerTests.swift */; }; CE57127C2CD109DB00D4AB17 /* OEXFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CE57127B2CD109DB00D4AB17 /* OEXFoundation */; }; CE7CAF392CC1561E00E0AC9D /* OEXFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CE7CAF382CC1561E00E0AC9D /* OEXFoundation */; }; - CE953A3B2CD0DA940023D667 /* CoreMock.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE953A3A2CD0DA940023D667 /* CoreMock.generated.swift */; }; + CE953A3B2CD0DA940023D667 /* CoreMocks.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE953A3A2CD0DA940023D667 /* CoreMocks.generated.swift */; }; CEC873BE2D75D55600A2626C /* CourseStructureManagerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC873BD2D75D55600A2626C /* CourseStructureManagerProtocol.swift */; }; CEC875392D7845DB00A2626C /* DeviceStorageFullAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC875372D7845DB00A2626C /* DeviceStorageFullAlertView.swift */; }; CEC8753A2D7845DB00A2626C /* DownloadActionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC875352D7845DB00A2626C /* DownloadActionView.swift */; }; @@ -375,7 +375,7 @@ CE38BBD62D9D8294002CD276 /* ExperimentalFeaturesConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExperimentalFeaturesConfig.swift; sourceTree = ""; }; CE54C2D12CC80D8500E529F9 /* DownloadManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadManagerTests.swift; sourceTree = ""; }; CE5BBFF32E24236500D51C92 /* ColorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorExtension.swift; sourceTree = ""; }; - CE953A3A2CD0DA940023D667 /* CoreMock.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreMock.generated.swift; sourceTree = ""; }; + CE953A3A2CD0DA940023D667 /* CoreMocks.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreMocks.generated.swift; sourceTree = ""; }; CEC873BD2D75D55600A2626C /* CourseStructureManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseStructureManagerProtocol.swift; sourceTree = ""; }; CEC875352D7845DB00A2626C /* DownloadActionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadActionView.swift; sourceTree = ""; }; CEC875362D7845DB00A2626C /* DownloadErrorAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadErrorAlertView.swift; sourceTree = ""; }; @@ -862,6 +862,14 @@ path = DownloadManager; sourceTree = ""; }; + CE953A3C2CD0DA940023D668 /* Generated */ = { + isa = PBXGroup; + children = ( + CE953A3A2CD0DA940023D667 /* CoreMocks.generated.swift */, + ); + path = Generated; + sourceTree = ""; + }; CEC875382D7845DB00A2626C /* ActionViews */ = { isa = PBXGroup; children = ( @@ -905,7 +913,7 @@ E09179FA2B0F204D002AB695 /* CoreTests */ = { isa = PBXGroup; children = ( - CE953A3A2CD0DA940023D667 /* CoreMock.generated.swift */, + CE953A3C2CD0DA940023D668 /* Generated */, CE54C2CE2CC80B4A00E529F9 /* DownloadManager */, E09179FB2B0F204D002AB695 /* Configuration */, ); @@ -949,10 +957,10 @@ buildConfigurationList = 07169476296D996900E3DED6 /* Build configuration list for PBXNativeTarget "CoreTests" */; buildPhases = ( F87EB93C339DD81527F250AE /* [CP] Check Pods Manifest.lock */, + CE953A3D2CD0DA940023D669 /* Generate Mockolo Mocks */, 07169465296D996800E3DED6 /* Sources */, 07169466296D996800E3DED6 /* Frameworks */, 07169467296D996800E3DED6 /* Resources */, - C9AA9371F83D4B112F310DB8 /* [CP] Copy Pods Resources */, CE7CAF3B2CC1561E00E0AC9D /* Embed Frameworks */, ); buildRules = ( @@ -1056,7 +1064,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 0770DE5A28D0B1E5006D8A5D /* SwiftGen */ = { + CE953A3D2CD0DA940023D669 /* Generate Mockolo Mocks */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; buildActionMask = 2147483647; @@ -1066,31 +1074,33 @@ ); inputPaths = ( ); - name = SwiftGen; + name = "Generate Mockolo Mocks"; outputFileListPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [[ -f \"${PODS_ROOT}/SwiftGen/bin/swiftgen\" ]]; then\n \"${PODS_ROOT}/SwiftGen/bin/swiftgen\"\nelse\n echo \"warning: SwiftGen is not installed. Run 'pod install --repo-update' to install it.\"\nfi\n"; + shellScript = "if which mockolo >/dev/null; then\n mockolo \\\n --sourcedirs \"${SRCROOT}/Core\" \\\n --destination \"${SRCROOT}/CoreTests/Generated/CoreMocks.generated.swift\" \\\n --mock-final \\\n --testable-imports \"Core\" \\\n --custom-imports \"Foundation\" \"SwiftUI\" \"Combine\"\nelse\n echo \"warning: mockolo not installed, download from https://github.com/uber/mockolo\"\nfi\n"; }; - C9AA9371F83D4B112F310DB8 /* [CP] Copy Pods Resources */ = { + 0770DE5A28D0B1E5006D8A5D /* SwiftGen */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Core-CoreTests/Pods-App-Core-CoreTests-resources-${CONFIGURATION}-input-files.xcfilelist", ); - name = "[CP] Copy Pods Resources"; + inputPaths = ( + ); + name = SwiftGen; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Core-CoreTests/Pods-App-Core-CoreTests-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App-Core-CoreTests/Pods-App-Core-CoreTests-resources.sh\"\n"; - showEnvVarsInLog = 0; + shellScript = "if [[ -f \"${PODS_ROOT}/SwiftGen/bin/swiftgen\" ]]; then\n \"${PODS_ROOT}/SwiftGen/bin/swiftgen\"\nelse\n echo \"warning: SwiftGen is not installed. Run 'pod install --repo-update' to install it.\"\nfi\n"; }; ED83AD5255805030E042D62A /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; @@ -1144,7 +1154,7 @@ buildActionMask = 2147483647; files = ( BAD9CA422B2B140100DE790A /* AgreementConfigTests.swift in Sources */, - CE953A3B2CD0DA940023D667 /* CoreMock.generated.swift in Sources */, + CE953A3B2CD0DA940023D667 /* CoreMocks.generated.swift in Sources */, E09179FD2B0F204E002AB695 /* ConfigTests.swift in Sources */, CE54C2D22CC80D8500E529F9 /* DownloadManagerTests.swift in Sources */, ); diff --git a/Core/Core/Analytics/CoreAnalytics.swift b/Core/Core/Analytics/CoreAnalytics.swift index 3f6315800..f52e12e97 100644 --- a/Core/Core/Analytics/CoreAnalytics.swift +++ b/Core/Core/Analytics/CoreAnalytics.swift @@ -7,7 +7,7 @@ import Foundation -//sourcery: AutoMockable +/// @mockable public protocol CoreAnalytics { func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) diff --git a/Core/Core/Configuration/BaseRouter.swift b/Core/Core/Configuration/BaseRouter.swift index c18d01c80..882094074 100644 --- a/Core/Core/Configuration/BaseRouter.swift +++ b/Core/Core/Configuration/BaseRouter.swift @@ -8,7 +8,7 @@ import Foundation import SwiftUI -//sourcery: AutoMockable +/// @mockable @MainActor public protocol BaseRouter: Sendable { diff --git a/Core/Core/Configuration/Config/Config.swift b/Core/Core/Configuration/Config/Config.swift index ed760b71c..8d0c4b9be 100644 --- a/Core/Core/Configuration/Config/Config.swift +++ b/Core/Core/Configuration/Config/Config.swift @@ -7,7 +7,7 @@ import Foundation -//sourcery: AutoMockable +/// @mockable public protocol ConfigProtocol: Sendable { var baseURL: URL { get } var baseSSOURL: URL { get } diff --git a/Core/Core/Configuration/Connectivity.swift b/Core/Core/Configuration/Connectivity.swift index 1168c41e1..0b5c57fdb 100644 --- a/Core/Core/Configuration/Connectivity.swift +++ b/Core/Core/Configuration/Connectivity.swift @@ -14,7 +14,7 @@ public enum InternetState: Sendable { case notReachable } -// sourcery: AutoMockable +/// @mockable @MainActor public protocol ConnectivityProtocol: Sendable { var isInternetAvaliable: Bool { get } diff --git a/Core/Core/Data/CoreStorage.swift b/Core/Core/Data/CoreStorage.swift index 841fffb9e..32b511f7b 100644 --- a/Core/Core/Data/CoreStorage.swift +++ b/Core/Core/Data/CoreStorage.swift @@ -7,7 +7,7 @@ import Foundation -//sourcery: AutoMockable +/// @mockable public protocol CoreStorage: Sendable { var accessToken: String? {get set} var refreshToken: String? {get set} diff --git a/Core/Core/Data/Persistence/CorePersistenceProtocol.swift b/Core/Core/Data/Persistence/CorePersistenceProtocol.swift index 44c299dbd..3e311becc 100644 --- a/Core/Core/Data/Persistence/CorePersistenceProtocol.swift +++ b/Core/Core/Data/Persistence/CorePersistenceProtocol.swift @@ -8,7 +8,7 @@ import CoreData import Combine -//sourcery: AutoMockable +/// @mockable public protocol CorePersistenceProtocol: Sendable { func set(userId: Int) func getUserID() -> Int? diff --git a/Core/Core/Domain/AuthInteractor.swift b/Core/Core/Domain/AuthInteractor.swift index 4c10910bb..96d387580 100644 --- a/Core/Core/Domain/AuthInteractor.swift +++ b/Core/Core/Domain/AuthInteractor.swift @@ -7,7 +7,7 @@ import Foundation -//sourcery: AutoMockable +/// @mockable public protocol AuthInteractorProtocol: Sendable { @discardableResult func login(username: String, password: String) async throws -> User diff --git a/Core/Core/Domain/CourseStructureManagerProtocol.swift b/Core/Core/Domain/CourseStructureManagerProtocol.swift index 72002aa5e..79a6d6aba 100644 --- a/Core/Core/Domain/CourseStructureManagerProtocol.swift +++ b/Core/Core/Domain/CourseStructureManagerProtocol.swift @@ -7,7 +7,7 @@ import Foundation -//sourcery: AutoMockable +/// @mockable public protocol CourseStructureManagerProtocol: Sendable { func getCourseBlocks(courseID: String) async throws -> CourseStructure func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure diff --git a/Core/Core/Domain/OfflineSyncInteractor.swift b/Core/Core/Domain/OfflineSyncInteractor.swift index 84f427022..4295ec651 100644 --- a/Core/Core/Domain/OfflineSyncInteractor.swift +++ b/Core/Core/Domain/OfflineSyncInteractor.swift @@ -7,7 +7,7 @@ import Foundation -//sourcery: AutoMockable +/// @mockable public protocol OfflineSyncInteractorProtocol: Sendable { func submitOfflineProgress(courseID: String, blockID: String, data: String) async throws -> Bool } diff --git a/Core/Core/Network/DownloadManager.swift b/Core/Core/Network/DownloadManager.swift index acf2450da..e02ba47ab 100644 --- a/Core/Core/Network/DownloadManager.swift +++ b/Core/Core/Network/DownloadManager.swift @@ -149,7 +149,7 @@ public class NoWiFiError: LocalizedError, @unchecked Sendable { public init() {} } -//sourcery: AutoMockable +/// @mockable public protocol DownloadManagerProtocol: Sendable { func getCurrentDownloadTask() async -> DownloadDataTask? func eventPublisher() -> AnyPublisher diff --git a/Core/Core/View/Base/CalendarManagerProtocol.swift b/Core/Core/View/Base/CalendarManagerProtocol.swift index 51bbe874d..309778e7c 100644 --- a/Core/Core/View/Base/CalendarManagerProtocol.swift +++ b/Core/Core/View/Base/CalendarManagerProtocol.swift @@ -7,7 +7,7 @@ import Foundation -//sourcery: AutoMockable +/// @mockable @MainActor public protocol CalendarManagerProtocol: Sendable { func createCalendarIfNeeded() diff --git a/Core/Core/View/Base/Webview/WebviewCookiesUpdateProtocol.swift b/Core/Core/View/Base/Webview/WebviewCookiesUpdateProtocol.swift index 707c615ef..0ffcdf3f3 100644 --- a/Core/Core/View/Base/Webview/WebviewCookiesUpdateProtocol.swift +++ b/Core/Core/View/Base/Webview/WebviewCookiesUpdateProtocol.swift @@ -7,8 +7,7 @@ import Foundation -//sourcery: AutoMockable - +/// @mockable @MainActor public protocol WebviewCookiesUpdateProtocol: AnyObject { var authInteractor: AuthInteractorProtocol { get } diff --git a/Core/CoreTests/CoreMock.generated.swift b/Core/CoreTests/CoreMock.generated.swift deleted file mode 100644 index dcc937551..000000000 --- a/Core/CoreTests/CoreMock.generated.swift +++ /dev/null @@ -1,4567 +0,0 @@ -// Generated using Sourcery 2.1.2 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT - - -// Generated with SwiftyMocky 4.2.0 -// Required Sourcery: 1.8.0 - - -import SwiftyMocky -import XCTest -import Core -import Foundation -import SwiftUI -import Combine - - -// MARK: - AuthInteractorProtocol - -open class AuthInteractorProtocolMock: AuthInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - @discardableResult - open func login(username: String, password: String) throws -> User { - addInvocation(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) - let perform = methodPerformValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) as? (String, String) -> Void - perform?(`username`, `password`) - var __value: User - do { - __value = try methodReturnValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(username: String, password: String). Use given") - Failure("Stub return value not specified for login(username: String, password: String). Use given") - } catch { - throw error - } - return __value - } - - @discardableResult - open func login(externalToken: String, backend: String) throws -> User { - addInvocation(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) - let perform = methodPerformValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) as? (String, String) -> Void - perform?(`externalToken`, `backend`) - var __value: User - do { - __value = try methodReturnValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - Failure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - } catch { - throw error - } - return __value - } - - open func login(ssoToken: String) throws -> User { - addInvocation(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) - let perform = methodPerformValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) as? (String) -> Void - perform?(`ssoToken`) - var __value: User - do { - __value = try methodReturnValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(ssoToken: String). Use given") - Failure("Stub return value not specified for login(ssoToken: String). Use given") - } catch { - throw error - } - return __value - } - - open func resetPassword(email: String) throws -> ResetPassword { - addInvocation(.m_resetPassword__email_email(Parameter.value(`email`))) - let perform = methodPerformValue(.m_resetPassword__email_email(Parameter.value(`email`))) as? (String) -> Void - perform?(`email`) - var __value: ResetPassword - do { - __value = try methodReturnValue(.m_resetPassword__email_email(Parameter.value(`email`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for resetPassword(email: String). Use given") - Failure("Stub return value not specified for resetPassword(email: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCookies(force: Bool) throws { - addInvocation(.m_getCookies__force_force(Parameter.value(`force`))) - let perform = methodPerformValue(.m_getCookies__force_force(Parameter.value(`force`))) as? (Bool) -> Void - perform?(`force`) - do { - _ = try methodReturnValue(.m_getCookies__force_force(Parameter.value(`force`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getRegistrationFields() throws -> [PickerFields] { - addInvocation(.m_getRegistrationFields) - let perform = methodPerformValue(.m_getRegistrationFields) as? () -> Void - perform?() - var __value: [PickerFields] - do { - __value = try methodReturnValue(.m_getRegistrationFields).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getRegistrationFields(). Use given") - Failure("Stub return value not specified for getRegistrationFields(). Use given") - } catch { - throw error - } - return __value - } - - open func registerUser(fields: [String: String], isSocial: Bool) throws -> User { - addInvocation(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) - let perform = methodPerformValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) as? ([String: String], Bool) -> Void - perform?(`fields`, `isSocial`) - var __value: User - do { - __value = try methodReturnValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - Failure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - } catch { - throw error - } - return __value - } - - open func validateRegistrationFields(fields: [String: String]) throws -> [String: String] { - addInvocation(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) - let perform = methodPerformValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) as? ([String: String]) -> Void - perform?(`fields`) - var __value: [String: String] - do { - __value = try methodReturnValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - Failure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_login__username_usernamepassword_password(Parameter, Parameter) - case m_login__externalToken_externalTokenbackend_backend(Parameter, Parameter) - case m_login__ssoToken_ssoToken(Parameter) - case m_resetPassword__email_email(Parameter) - case m_getCookies__force_force(Parameter) - case m_getRegistrationFields - case m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>, Parameter) - case m_validateRegistrationFields__fields_fields(Parameter<[String: String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_login__username_usernamepassword_password(let lhsUsername, let lhsPassword), .m_login__username_usernamepassword_password(let rhsUsername, let rhsPassword)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsername, rhs: rhsUsername, with: matcher), lhsUsername, rhsUsername, "username")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPassword, rhs: rhsPassword, with: matcher), lhsPassword, rhsPassword, "password")) - return Matcher.ComparisonResult(results) - - case (.m_login__externalToken_externalTokenbackend_backend(let lhsExternaltoken, let lhsBackend), .m_login__externalToken_externalTokenbackend_backend(let rhsExternaltoken, let rhsBackend)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsExternaltoken, rhs: rhsExternaltoken, with: matcher), lhsExternaltoken, rhsExternaltoken, "externalToken")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBackend, rhs: rhsBackend, with: matcher), lhsBackend, rhsBackend, "backend")) - return Matcher.ComparisonResult(results) - - case (.m_login__ssoToken_ssoToken(let lhsSsotoken), .m_login__ssoToken_ssoToken(let rhsSsotoken)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSsotoken, rhs: rhsSsotoken, with: matcher), lhsSsotoken, rhsSsotoken, "ssoToken")) - return Matcher.ComparisonResult(results) - - case (.m_resetPassword__email_email(let lhsEmail), .m_resetPassword__email_email(let rhsEmail)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEmail, rhs: rhsEmail, with: matcher), lhsEmail, rhsEmail, "email")) - return Matcher.ComparisonResult(results) - - case (.m_getCookies__force_force(let lhsForce), .m_getCookies__force_force(let rhsForce)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsForce, rhs: rhsForce, with: matcher), lhsForce, rhsForce, "force")) - return Matcher.ComparisonResult(results) - - case (.m_getRegistrationFields, .m_getRegistrationFields): return .match - - case (.m_registerUser__fields_fieldsisSocial_isSocial(let lhsFields, let lhsIssocial), .m_registerUser__fields_fieldsisSocial_isSocial(let rhsFields, let rhsIssocial)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIssocial, rhs: rhsIssocial, with: matcher), lhsIssocial, rhsIssocial, "isSocial")) - return Matcher.ComparisonResult(results) - - case (.m_validateRegistrationFields__fields_fields(let lhsFields), .m_validateRegistrationFields__fields_fields(let rhsFields)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_login__username_usernamepassword_password(p0, p1): return p0.intValue + p1.intValue - case let .m_login__externalToken_externalTokenbackend_backend(p0, p1): return p0.intValue + p1.intValue - case let .m_login__ssoToken_ssoToken(p0): return p0.intValue - case let .m_resetPassword__email_email(p0): return p0.intValue - case let .m_getCookies__force_force(p0): return p0.intValue - case .m_getRegistrationFields: return 0 - case let .m_registerUser__fields_fieldsisSocial_isSocial(p0, p1): return p0.intValue + p1.intValue - case let .m_validateRegistrationFields__fields_fields(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_login__username_usernamepassword_password: return ".login(username:password:)" - case .m_login__externalToken_externalTokenbackend_backend: return ".login(externalToken:backend:)" - case .m_login__ssoToken_ssoToken: return ".login(ssoToken:)" - case .m_resetPassword__email_email: return ".resetPassword(email:)" - case .m_getCookies__force_force: return ".getCookies(force:)" - case .m_getRegistrationFields: return ".getRegistrationFields()" - case .m_registerUser__fields_fieldsisSocial_isSocial: return ".registerUser(fields:isSocial:)" - case .m_validateRegistrationFields__fields_fields: return ".validateRegistrationFields(fields:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - @discardableResult - public static func login(username: Parameter, password: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func login(ssoToken: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func resetPassword(email: Parameter, willReturn: ResetPassword...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getRegistrationFields(willReturn: [PickerFields]...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willReturn: [String: String]...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func login(ssoToken: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func login(ssoToken: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func resetPassword(email: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resetPassword(email: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (ResetPassword).self) - willProduce(stubber) - return given - } - public static func getCookies(force: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCookies(force: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func getRegistrationFields(willThrow: Error...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getRegistrationFields(willProduce: (StubberThrows<[PickerFields]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([PickerFields]).self) - willProduce(stubber) - return given - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willProduce: (StubberThrows<[String: String]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([String: String]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - @discardableResult - public static func login(username: Parameter, password: Parameter) -> Verify { return Verify(method: .m_login__username_usernamepassword_password(`username`, `password`))} - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter) -> Verify { return Verify(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`))} - public static func login(ssoToken: Parameter) -> Verify { return Verify(method: .m_login__ssoToken_ssoToken(`ssoToken`))} - public static func resetPassword(email: Parameter) -> Verify { return Verify(method: .m_resetPassword__email_email(`email`))} - public static func getCookies(force: Parameter) -> Verify { return Verify(method: .m_getCookies__force_force(`force`))} - public static func getRegistrationFields() -> Verify { return Verify(method: .m_getRegistrationFields)} - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter) -> Verify { return Verify(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`))} - public static func validateRegistrationFields(fields: Parameter<[String: String]>) -> Verify { return Verify(method: .m_validateRegistrationFields__fields_fields(`fields`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - @discardableResult - public static func login(username: Parameter, password: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__username_usernamepassword_password(`username`, `password`), performs: perform) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), performs: perform) - } - public static func login(ssoToken: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_login__ssoToken_ssoToken(`ssoToken`), performs: perform) - } - public static func resetPassword(email: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_resetPassword__email_email(`email`), performs: perform) - } - public static func getCookies(force: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_getCookies__force_force(`force`), performs: perform) - } - public static func getRegistrationFields(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getRegistrationFields, performs: perform) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, perform: @escaping ([String: String], Bool) -> Void) -> Perform { - return Perform(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), performs: perform) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, perform: @escaping ([String: String]) -> Void) -> Perform { - return Perform(method: .m_validateRegistrationFields__fields_fields(`fields`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - BaseRouter -@MainActor -open class BaseRouterMock: BaseRouter, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func backToRoot(animated: Bool) { - addInvocation(.m_backToRoot__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_backToRoot__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func back(animated: Bool) { - addInvocation(.m_back__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_back__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func backWithFade() { - addInvocation(.m_backWithFade) - let perform = methodPerformValue(.m_backWithFade) as? () -> Void - perform?() - } - - open func dismiss(animated: Bool) { - addInvocation(.m_dismiss__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_dismiss__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func removeLastView(controllers: Int) { - addInvocation(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) - let perform = methodPerformValue(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) as? (Int) -> Void - perform?(`controllers`) - } - - open func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { - addInvocation(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) - let perform = methodPerformValue(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) as? (LogistrationSourceScreen, PostLoginData?) -> Void - perform?(`sourceScreen`, `postLoginData`) - } - - open func showStartupScreen() { - addInvocation(.m_showStartupScreen) - let perform = methodPerformValue(.m_showStartupScreen) as? () -> Void - perform?() - } - - open func showLoginScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showForgotPasswordScreen() { - addInvocation(.m_showForgotPasswordScreen) - let perform = methodPerformValue(.m_showForgotPasswordScreen) as? () -> Void - perform?() - } - - open func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) as? (String?, LogistrationSourceScreen) -> Void - perform?(`searchQuery`, `sourceScreen`) - } - - open func showWebBrowser(title: String, url: URL) { - addInvocation(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) - let perform = methodPerformValue(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) as? (String, URL) -> Void - perform?(`title`, `url`) - } - - open func showSSOWebBrowser(title: String) { - addInvocation(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) - let perform = methodPerformValue(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) as? (String) -> Void - perform?(`title`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) as? (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void - perform?(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) as? (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void - perform?(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { - addInvocation(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) as? (UIModalTransitionStyle, any View, (() -> Void)?) -> Void - perform?(`transitionStyle`, `view`, `completion`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { - addInvocation(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) as? (UIModalTransitionStyle, Bool, () -> any View) -> Void - perform?(`transitionStyle`, `animated`, `content`) - } - - - fileprivate enum MethodType { - case m_backToRoot__animated_animated(Parameter) - case m_back__animated_animated(Parameter) - case m_backWithFade - case m_dismiss__animated_animated(Parameter) - case m_removeLastView__controllers_controllers(Parameter) - case m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter, Parameter) - case m_showStartupScreen - case m_showLoginScreen__sourceScreen_sourceScreen(Parameter) - case m_showRegisterScreen__sourceScreen_sourceScreen(Parameter) - case m_showForgotPasswordScreen - case m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter, Parameter) - case m_showWebBrowser__title_titleurl_url(Parameter, Parameter) - case m_showSSOWebBrowser__title_title(Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter<() -> Void>) - case m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter, Parameter, Parameter<(() -> Void)?>) - case m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter, Parameter, Parameter<() -> any View>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_backToRoot__animated_animated(let lhsAnimated), .m_backToRoot__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_back__animated_animated(let lhsAnimated), .m_back__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_backWithFade, .m_backWithFade): return .match - - case (.m_dismiss__animated_animated(let lhsAnimated), .m_dismiss__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_removeLastView__controllers_controllers(let lhsControllers), .m_removeLastView__controllers_controllers(let rhsControllers)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsControllers, rhs: rhsControllers, with: matcher), lhsControllers, rhsControllers, "controllers")) - return Matcher.ComparisonResult(results) - - case (.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let lhsSourcescreen, let lhsPostlogindata), .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let rhsSourcescreen, let rhsPostlogindata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPostlogindata, rhs: rhsPostlogindata, with: matcher), lhsPostlogindata, rhsPostlogindata, "postLoginData")) - return Matcher.ComparisonResult(results) - - case (.m_showStartupScreen, .m_showStartupScreen): return .match - - case (.m_showLoginScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showLoginScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showRegisterScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showRegisterScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showForgotPasswordScreen, .m_showForgotPasswordScreen): return .match - - case (.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let lhsSearchquery, let lhsSourcescreen), .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let rhsSearchquery, let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchquery, rhs: rhsSearchquery, with: matcher), lhsSearchquery, rhsSearchquery, "searchQuery")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showWebBrowser__title_titleurl_url(let lhsTitle, let lhsUrl), .m_showWebBrowser__title_titleurl_url(let rhsTitle, let rhsUrl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - return Matcher.ComparisonResult(results) - - case (.m_showSSOWebBrowser__title_title(let lhsTitle), .m_showSSOWebBrowser__title_title(let rhsTitle)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let lhsAlerttitle, let lhsAlertmessage, let lhsPositiveaction, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsType), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let rhsAlerttitle, let rhsAlertmessage, let rhsPositiveaction, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPositiveaction, rhs: rhsPositiveaction, with: matcher), lhsPositiveaction, rhsPositiveaction, "positiveAction")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let lhsAlerttitle, let lhsAlertmessage, let lhsNextsectionname, let lhsAction, let lhsImage, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsNextsectiontapped), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let rhsAlerttitle, let rhsAlertmessage, let rhsNextsectionname, let rhsAction, let rhsImage, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsNextsectiontapped)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectionname, rhs: rhsNextsectionname, with: matcher), lhsNextsectionname, rhsNextsectionname, "nextSectionName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsImage, rhs: rhsImage, with: matcher), lhsImage, rhsImage, "image")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectiontapped, rhs: rhsNextsectiontapped, with: matcher), lhsNextsectiontapped, rhsNextsectiontapped, "nextSectionTapped")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let lhsTransitionstyle, let lhsView, let lhsCompletion), .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let rhsTransitionstyle, let rhsView, let rhsCompletion)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsView, rhs: rhsView, with: matcher), lhsView, rhsView, "view")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCompletion, rhs: rhsCompletion, with: matcher), lhsCompletion, rhsCompletion, "completion")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let lhsTransitionstyle, let lhsAnimated, let lhsContent), .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let rhsTransitionstyle, let rhsAnimated, let rhsContent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsContent, rhs: rhsContent, with: matcher), lhsContent, rhsContent, "content")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_backToRoot__animated_animated(p0): return p0.intValue - case let .m_back__animated_animated(p0): return p0.intValue - case .m_backWithFade: return 0 - case let .m_dismiss__animated_animated(p0): return p0.intValue - case let .m_removeLastView__controllers_controllers(p0): return p0.intValue - case let .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(p0, p1): return p0.intValue + p1.intValue - case .m_showStartupScreen: return 0 - case let .m_showLoginScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case let .m_showRegisterScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case .m_showForgotPasswordScreen: return 0 - case let .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(p0, p1): return p0.intValue + p1.intValue - case let .m_showWebBrowser__title_titleurl_url(p0, p1): return p0.intValue + p1.intValue - case let .m_showSSOWebBrowser__title_title(p0): return p0.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(p0, p1, p2, p3, p4, p5, p6, p7): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue + p7.intValue - case let .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_backToRoot__animated_animated: return ".backToRoot(animated:)" - case .m_back__animated_animated: return ".back(animated:)" - case .m_backWithFade: return ".backWithFade()" - case .m_dismiss__animated_animated: return ".dismiss(animated:)" - case .m_removeLastView__controllers_controllers: return ".removeLastView(controllers:)" - case .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData: return ".showMainOrWhatsNewScreen(sourceScreen:postLoginData:)" - case .m_showStartupScreen: return ".showStartupScreen()" - case .m_showLoginScreen__sourceScreen_sourceScreen: return ".showLoginScreen(sourceScreen:)" - case .m_showRegisterScreen__sourceScreen_sourceScreen: return ".showRegisterScreen(sourceScreen:)" - case .m_showForgotPasswordScreen: return ".showForgotPasswordScreen()" - case .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen: return ".showDiscoveryScreen(searchQuery:sourceScreen:)" - case .m_showWebBrowser__title_titleurl_url: return ".showWebBrowser(title:url:)" - case .m_showSSOWebBrowser__title_title: return ".showSSOWebBrowser(title:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type: return ".presentAlert(alertTitle:alertMessage:positiveAction:onCloseTapped:firstButtonTapped:type:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped: return ".presentAlert(alertTitle:alertMessage:nextSectionName:action:image:onCloseTapped:firstButtonTapped:nextSectionTapped:)" - case .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion: return ".presentView(transitionStyle:view:completion:)" - case .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content: return ".presentView(transitionStyle:animated:content:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func backToRoot(animated: Parameter) -> Verify { return Verify(method: .m_backToRoot__animated_animated(`animated`))} - public static func back(animated: Parameter) -> Verify { return Verify(method: .m_back__animated_animated(`animated`))} - public static func backWithFade() -> Verify { return Verify(method: .m_backWithFade)} - public static func dismiss(animated: Parameter) -> Verify { return Verify(method: .m_dismiss__animated_animated(`animated`))} - public static func removeLastView(controllers: Parameter) -> Verify { return Verify(method: .m_removeLastView__controllers_controllers(`controllers`))} - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter) -> Verify { return Verify(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`))} - public static func showStartupScreen() -> Verify { return Verify(method: .m_showStartupScreen)} - public static func showLoginScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showRegisterScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showForgotPasswordScreen() -> Verify { return Verify(method: .m_showForgotPasswordScreen)} - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter) -> Verify { return Verify(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`))} - public static func showWebBrowser(title: Parameter, url: Parameter) -> Verify { return Verify(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`))} - public static func showSSOWebBrowser(title: Parameter) -> Verify { return Verify(method: .m_showSSOWebBrowser__title_title(`title`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`))} - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`))} - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func backToRoot(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_backToRoot__animated_animated(`animated`), performs: perform) - } - public static func back(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_back__animated_animated(`animated`), performs: perform) - } - public static func backWithFade(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_backWithFade, performs: perform) - } - public static func dismiss(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_dismiss__animated_animated(`animated`), performs: perform) - } - public static func removeLastView(controllers: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_removeLastView__controllers_controllers(`controllers`), performs: perform) - } - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter, perform: @escaping (LogistrationSourceScreen, PostLoginData?) -> Void) -> Perform { - return Perform(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`), performs: perform) - } - public static func showStartupScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showStartupScreen, performs: perform) - } - public static func showLoginScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showRegisterScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showForgotPasswordScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showForgotPasswordScreen, performs: perform) - } - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter, perform: @escaping (String?, LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`), performs: perform) - } - public static func showWebBrowser(title: Parameter, url: Parameter, perform: @escaping (String, URL) -> Void) -> Perform { - return Perform(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`), performs: perform) - } - public static func showSSOWebBrowser(title: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showSSOWebBrowser__title_title(`title`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter, perform: @escaping (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>, perform: @escaping (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>, perform: @escaping (UIModalTransitionStyle, any View, (() -> Void)?) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>, perform: @escaping (UIModalTransitionStyle, Bool, () -> any View) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CalendarManagerProtocol -@MainActor -open class CalendarManagerProtocolMock: CalendarManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func createCalendarIfNeeded() { - addInvocation(.m_createCalendarIfNeeded) - let perform = methodPerformValue(.m_createCalendarIfNeeded) as? () -> Void - perform?() - } - - open func filterCoursesBySelected(fetchedCourses: [CourseForSync]) -> [CourseForSync] { - addInvocation(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) - let perform = methodPerformValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) as? ([CourseForSync]) -> Void - perform?(`fetchedCourses`) - var __value: [CourseForSync] - do { - __value = try methodReturnValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))).casted() - } catch { - onFatalFailure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - Failure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - } - return __value - } - - open func removeOldCalendar() { - addInvocation(.m_removeOldCalendar) - let perform = methodPerformValue(.m_removeOldCalendar) as? () -> Void - perform?() - } - - open func removeOutdatedEvents(courseID: String) { - addInvocation(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - } - - open func syncCourse(courseID: String, courseName: String, dates: CourseDates) { - addInvocation(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) - let perform = methodPerformValue(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) as? (String, String, CourseDates) -> Void - perform?(`courseID`, `courseName`, `dates`) - } - - open func requestAccess() -> Bool { - addInvocation(.m_requestAccess) - let perform = methodPerformValue(.m_requestAccess) as? () -> Void - perform?() - var __value: Bool - do { - __value = try methodReturnValue(.m_requestAccess).casted() - } catch { - onFatalFailure("Stub return value not specified for requestAccess(). Use given") - Failure("Stub return value not specified for requestAccess(). Use given") - } - return __value - } - - open func courseStatus(courseID: String) -> SyncStatus { - addInvocation(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: SyncStatus - do { - __value = try methodReturnValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for courseStatus(courseID: String). Use given") - Failure("Stub return value not specified for courseStatus(courseID: String). Use given") - } - return __value - } - - open func clearAllData(removeCalendar: Bool) { - addInvocation(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) - let perform = methodPerformValue(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) as? (Bool) -> Void - perform?(`removeCalendar`) - } - - open func isDatesChanged(courseID: String, checksum: String) -> Bool { - addInvocation(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) - let perform = methodPerformValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) as? (String, String) -> Void - perform?(`courseID`, `checksum`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - Failure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - } - return __value - } - - - fileprivate enum MethodType { - case m_createCalendarIfNeeded - case m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>) - case m_removeOldCalendar - case m_removeOutdatedEvents__courseID_courseID(Parameter) - case m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter, Parameter, Parameter) - case m_requestAccess - case m_courseStatus__courseID_courseID(Parameter) - case m_clearAllData__removeCalendar_removeCalendar(Parameter) - case m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_createCalendarIfNeeded, .m_createCalendarIfNeeded): return .match - - case (.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let lhsFetchedcourses), .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let rhsFetchedcourses)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFetchedcourses, rhs: rhsFetchedcourses, with: matcher), lhsFetchedcourses, rhsFetchedcourses, "fetchedCourses")) - return Matcher.ComparisonResult(results) - - case (.m_removeOldCalendar, .m_removeOldCalendar): return .match - - case (.m_removeOutdatedEvents__courseID_courseID(let lhsCourseid), .m_removeOutdatedEvents__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let lhsCourseid, let lhsCoursename, let lhsDates), .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let rhsCourseid, let rhsCoursename, let rhsDates)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDates, rhs: rhsDates, with: matcher), lhsDates, rhsDates, "dates")) - return Matcher.ComparisonResult(results) - - case (.m_requestAccess, .m_requestAccess): return .match - - case (.m_courseStatus__courseID_courseID(let lhsCourseid), .m_courseStatus__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_clearAllData__removeCalendar_removeCalendar(let lhsRemovecalendar), .m_clearAllData__removeCalendar_removeCalendar(let rhsRemovecalendar)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRemovecalendar, rhs: rhsRemovecalendar, with: matcher), lhsRemovecalendar, rhsRemovecalendar, "removeCalendar")) - return Matcher.ComparisonResult(results) - - case (.m_isDatesChanged__courseID_courseIDchecksum_checksum(let lhsCourseid, let lhsChecksum), .m_isDatesChanged__courseID_courseIDchecksum_checksum(let rhsCourseid, let rhsChecksum)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsChecksum, rhs: rhsChecksum, with: matcher), lhsChecksum, rhsChecksum, "checksum")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_createCalendarIfNeeded: return 0 - case let .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(p0): return p0.intValue - case .m_removeOldCalendar: return 0 - case let .m_removeOutdatedEvents__courseID_courseID(p0): return p0.intValue - case let .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case .m_requestAccess: return 0 - case let .m_courseStatus__courseID_courseID(p0): return p0.intValue - case let .m_clearAllData__removeCalendar_removeCalendar(p0): return p0.intValue - case let .m_isDatesChanged__courseID_courseIDchecksum_checksum(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_createCalendarIfNeeded: return ".createCalendarIfNeeded()" - case .m_filterCoursesBySelected__fetchedCourses_fetchedCourses: return ".filterCoursesBySelected(fetchedCourses:)" - case .m_removeOldCalendar: return ".removeOldCalendar()" - case .m_removeOutdatedEvents__courseID_courseID: return ".removeOutdatedEvents(courseID:)" - case .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates: return ".syncCourse(courseID:courseName:dates:)" - case .m_requestAccess: return ".requestAccess()" - case .m_courseStatus__courseID_courseID: return ".courseStatus(courseID:)" - case .m_clearAllData__removeCalendar_removeCalendar: return ".clearAllData(removeCalendar:)" - case .m_isDatesChanged__courseID_courseIDchecksum_checksum: return ".isDatesChanged(courseID:checksum:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willReturn: [CourseForSync]...) -> MethodStub { - return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func requestAccess(willReturn: Bool...) -> MethodStub { - return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func courseStatus(courseID: Parameter, willReturn: SyncStatus...) -> MethodStub { - return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willProduce: (Stubber<[CourseForSync]>) -> Void) -> MethodStub { - let willReturn: [[CourseForSync]] = [] - let given: Given = { return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([CourseForSync]).self) - willProduce(stubber) - return given - } - public static func requestAccess(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func courseStatus(courseID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [SyncStatus] = [] - let given: Given = { return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (SyncStatus).self) - willProduce(stubber) - return given - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func createCalendarIfNeeded() -> Verify { return Verify(method: .m_createCalendarIfNeeded)} - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>) -> Verify { return Verify(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`))} - public static func removeOldCalendar() -> Verify { return Verify(method: .m_removeOldCalendar)} - public static func removeOutdatedEvents(courseID: Parameter) -> Verify { return Verify(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`))} - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter) -> Verify { return Verify(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`))} - public static func requestAccess() -> Verify { return Verify(method: .m_requestAccess)} - public static func courseStatus(courseID: Parameter) -> Verify { return Verify(method: .m_courseStatus__courseID_courseID(`courseID`))} - public static func clearAllData(removeCalendar: Parameter) -> Verify { return Verify(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`))} - public static func isDatesChanged(courseID: Parameter, checksum: Parameter) -> Verify { return Verify(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func createCalendarIfNeeded(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_createCalendarIfNeeded, performs: perform) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, perform: @escaping ([CourseForSync]) -> Void) -> Perform { - return Perform(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), performs: perform) - } - public static func removeOldCalendar(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeOldCalendar, performs: perform) - } - public static func removeOutdatedEvents(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`), performs: perform) - } - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter, perform: @escaping (String, String, CourseDates) -> Void) -> Perform { - return Perform(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`), performs: perform) - } - public static func requestAccess(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_requestAccess, performs: perform) - } - public static func courseStatus(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_courseStatus__courseID_courseID(`courseID`), performs: perform) - } - public static func clearAllData(removeCalendar: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`), performs: perform) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConfigProtocol - -open class ConfigProtocolMock: ConfigProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var baseURL: URL { - get { invocations.append(.p_baseURL_get); return __p_baseURL ?? givenGetterValue(.p_baseURL_get, "ConfigProtocolMock - stub value for baseURL was not defined") } - } - private var __p_baseURL: (URL)? - - public var baseSSOURL: URL { - get { invocations.append(.p_baseSSOURL_get); return __p_baseSSOURL ?? givenGetterValue(.p_baseSSOURL_get, "ConfigProtocolMock - stub value for baseSSOURL was not defined") } - } - private var __p_baseSSOURL: (URL)? - - public var ssoFinishedURL: URL { - get { invocations.append(.p_ssoFinishedURL_get); return __p_ssoFinishedURL ?? givenGetterValue(.p_ssoFinishedURL_get, "ConfigProtocolMock - stub value for ssoFinishedURL was not defined") } - } - private var __p_ssoFinishedURL: (URL)? - - public var ssoButtonTitle: [String: Any] { - get { invocations.append(.p_ssoButtonTitle_get); return __p_ssoButtonTitle ?? givenGetterValue(.p_ssoButtonTitle_get, "ConfigProtocolMock - stub value for ssoButtonTitle was not defined") } - } - private var __p_ssoButtonTitle: ([String: Any])? - - public var oAuthClientId: String { - get { invocations.append(.p_oAuthClientId_get); return __p_oAuthClientId ?? givenGetterValue(.p_oAuthClientId_get, "ConfigProtocolMock - stub value for oAuthClientId was not defined") } - } - private var __p_oAuthClientId: (String)? - - public var tokenType: TokenType { - get { invocations.append(.p_tokenType_get); return __p_tokenType ?? givenGetterValue(.p_tokenType_get, "ConfigProtocolMock - stub value for tokenType was not defined") } - } - private var __p_tokenType: (TokenType)? - - public var feedbackEmail: String { - get { invocations.append(.p_feedbackEmail_get); return __p_feedbackEmail ?? givenGetterValue(.p_feedbackEmail_get, "ConfigProtocolMock - stub value for feedbackEmail was not defined") } - } - private var __p_feedbackEmail: (String)? - - public var appStoreLink: String { - get { invocations.append(.p_appStoreLink_get); return __p_appStoreLink ?? givenGetterValue(.p_appStoreLink_get, "ConfigProtocolMock - stub value for appStoreLink was not defined") } - } - private var __p_appStoreLink: (String)? - - public var faq: URL? { - get { invocations.append(.p_faq_get); return __p_faq ?? optionalGivenGetterValue(.p_faq_get, "ConfigProtocolMock - stub value for faq was not defined") } - } - private var __p_faq: (URL)? - - public var platformName: String { - get { invocations.append(.p_platformName_get); return __p_platformName ?? givenGetterValue(.p_platformName_get, "ConfigProtocolMock - stub value for platformName was not defined") } - } - private var __p_platformName: (String)? - - public var agreement: AgreementConfig { - get { invocations.append(.p_agreement_get); return __p_agreement ?? givenGetterValue(.p_agreement_get, "ConfigProtocolMock - stub value for agreement was not defined") } - } - private var __p_agreement: (AgreementConfig)? - - public var firebase: FirebaseConfig { - get { invocations.append(.p_firebase_get); return __p_firebase ?? givenGetterValue(.p_firebase_get, "ConfigProtocolMock - stub value for firebase was not defined") } - } - private var __p_firebase: (FirebaseConfig)? - - public var facebook: FacebookConfig { - get { invocations.append(.p_facebook_get); return __p_facebook ?? givenGetterValue(.p_facebook_get, "ConfigProtocolMock - stub value for facebook was not defined") } - } - private var __p_facebook: (FacebookConfig)? - - public var microsoft: MicrosoftConfig { - get { invocations.append(.p_microsoft_get); return __p_microsoft ?? givenGetterValue(.p_microsoft_get, "ConfigProtocolMock - stub value for microsoft was not defined") } - } - private var __p_microsoft: (MicrosoftConfig)? - - public var google: GoogleConfig { - get { invocations.append(.p_google_get); return __p_google ?? givenGetterValue(.p_google_get, "ConfigProtocolMock - stub value for google was not defined") } - } - private var __p_google: (GoogleConfig)? - - public var appleSignIn: AppleSignInConfig { - get { invocations.append(.p_appleSignIn_get); return __p_appleSignIn ?? givenGetterValue(.p_appleSignIn_get, "ConfigProtocolMock - stub value for appleSignIn was not defined") } - } - private var __p_appleSignIn: (AppleSignInConfig)? - - public var features: FeaturesConfig { - get { invocations.append(.p_features_get); return __p_features ?? givenGetterValue(.p_features_get, "ConfigProtocolMock - stub value for features was not defined") } - } - private var __p_features: (FeaturesConfig)? - - public var theme: ThemeConfig { - get { invocations.append(.p_theme_get); return __p_theme ?? givenGetterValue(.p_theme_get, "ConfigProtocolMock - stub value for theme was not defined") } - } - private var __p_theme: (ThemeConfig)? - - public var uiComponents: UIComponentsConfig { - get { invocations.append(.p_uiComponents_get); return __p_uiComponents ?? givenGetterValue(.p_uiComponents_get, "ConfigProtocolMock - stub value for uiComponents was not defined") } - } - private var __p_uiComponents: (UIComponentsConfig)? - - public var discovery: DiscoveryConfig { - get { invocations.append(.p_discovery_get); return __p_discovery ?? givenGetterValue(.p_discovery_get, "ConfigProtocolMock - stub value for discovery was not defined") } - } - private var __p_discovery: (DiscoveryConfig)? - - public var dashboard: DashboardConfig { - get { invocations.append(.p_dashboard_get); return __p_dashboard ?? givenGetterValue(.p_dashboard_get, "ConfigProtocolMock - stub value for dashboard was not defined") } - } - private var __p_dashboard: (DashboardConfig)? - - public var braze: BrazeConfig { - get { invocations.append(.p_braze_get); return __p_braze ?? givenGetterValue(.p_braze_get, "ConfigProtocolMock - stub value for braze was not defined") } - } - private var __p_braze: (BrazeConfig)? - - public var branch: BranchConfig { - get { invocations.append(.p_branch_get); return __p_branch ?? givenGetterValue(.p_branch_get, "ConfigProtocolMock - stub value for branch was not defined") } - } - private var __p_branch: (BranchConfig)? - - public var program: DiscoveryConfig { - get { invocations.append(.p_program_get); return __p_program ?? givenGetterValue(.p_program_get, "ConfigProtocolMock - stub value for program was not defined") } - } - private var __p_program: (DiscoveryConfig)? - - public var experimentalFeatures: ExperimentalFeaturesConfig { - get { invocations.append(.p_experimentalFeatures_get); return __p_experimentalFeatures ?? givenGetterValue(.p_experimentalFeatures_get, "ConfigProtocolMock - stub value for experimentalFeatures was not defined") } - } - private var __p_experimentalFeatures: (ExperimentalFeaturesConfig)? - - public var URIScheme: String { - get { invocations.append(.p_URIScheme_get); return __p_URIScheme ?? givenGetterValue(.p_URIScheme_get, "ConfigProtocolMock - stub value for URIScheme was not defined") } - } - private var __p_URIScheme: (String)? - - - - - - - fileprivate enum MethodType { - case p_baseURL_get - case p_baseSSOURL_get - case p_ssoFinishedURL_get - case p_ssoButtonTitle_get - case p_oAuthClientId_get - case p_tokenType_get - case p_feedbackEmail_get - case p_appStoreLink_get - case p_faq_get - case p_platformName_get - case p_agreement_get - case p_firebase_get - case p_facebook_get - case p_microsoft_get - case p_google_get - case p_appleSignIn_get - case p_features_get - case p_theme_get - case p_uiComponents_get - case p_discovery_get - case p_dashboard_get - case p_braze_get - case p_branch_get - case p_program_get - case p_experimentalFeatures_get - case p_URIScheme_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_baseURL_get,.p_baseURL_get): return Matcher.ComparisonResult.match - case (.p_baseSSOURL_get,.p_baseSSOURL_get): return Matcher.ComparisonResult.match - case (.p_ssoFinishedURL_get,.p_ssoFinishedURL_get): return Matcher.ComparisonResult.match - case (.p_ssoButtonTitle_get,.p_ssoButtonTitle_get): return Matcher.ComparisonResult.match - case (.p_oAuthClientId_get,.p_oAuthClientId_get): return Matcher.ComparisonResult.match - case (.p_tokenType_get,.p_tokenType_get): return Matcher.ComparisonResult.match - case (.p_feedbackEmail_get,.p_feedbackEmail_get): return Matcher.ComparisonResult.match - case (.p_appStoreLink_get,.p_appStoreLink_get): return Matcher.ComparisonResult.match - case (.p_faq_get,.p_faq_get): return Matcher.ComparisonResult.match - case (.p_platformName_get,.p_platformName_get): return Matcher.ComparisonResult.match - case (.p_agreement_get,.p_agreement_get): return Matcher.ComparisonResult.match - case (.p_firebase_get,.p_firebase_get): return Matcher.ComparisonResult.match - case (.p_facebook_get,.p_facebook_get): return Matcher.ComparisonResult.match - case (.p_microsoft_get,.p_microsoft_get): return Matcher.ComparisonResult.match - case (.p_google_get,.p_google_get): return Matcher.ComparisonResult.match - case (.p_appleSignIn_get,.p_appleSignIn_get): return Matcher.ComparisonResult.match - case (.p_features_get,.p_features_get): return Matcher.ComparisonResult.match - case (.p_theme_get,.p_theme_get): return Matcher.ComparisonResult.match - case (.p_uiComponents_get,.p_uiComponents_get): return Matcher.ComparisonResult.match - case (.p_discovery_get,.p_discovery_get): return Matcher.ComparisonResult.match - case (.p_dashboard_get,.p_dashboard_get): return Matcher.ComparisonResult.match - case (.p_braze_get,.p_braze_get): return Matcher.ComparisonResult.match - case (.p_branch_get,.p_branch_get): return Matcher.ComparisonResult.match - case (.p_program_get,.p_program_get): return Matcher.ComparisonResult.match - case (.p_experimentalFeatures_get,.p_experimentalFeatures_get): return Matcher.ComparisonResult.match - case (.p_URIScheme_get,.p_URIScheme_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_baseURL_get: return 0 - case .p_baseSSOURL_get: return 0 - case .p_ssoFinishedURL_get: return 0 - case .p_ssoButtonTitle_get: return 0 - case .p_oAuthClientId_get: return 0 - case .p_tokenType_get: return 0 - case .p_feedbackEmail_get: return 0 - case .p_appStoreLink_get: return 0 - case .p_faq_get: return 0 - case .p_platformName_get: return 0 - case .p_agreement_get: return 0 - case .p_firebase_get: return 0 - case .p_facebook_get: return 0 - case .p_microsoft_get: return 0 - case .p_google_get: return 0 - case .p_appleSignIn_get: return 0 - case .p_features_get: return 0 - case .p_theme_get: return 0 - case .p_uiComponents_get: return 0 - case .p_discovery_get: return 0 - case .p_dashboard_get: return 0 - case .p_braze_get: return 0 - case .p_branch_get: return 0 - case .p_program_get: return 0 - case .p_experimentalFeatures_get: return 0 - case .p_URIScheme_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_baseURL_get: return "[get] .baseURL" - case .p_baseSSOURL_get: return "[get] .baseSSOURL" - case .p_ssoFinishedURL_get: return "[get] .ssoFinishedURL" - case .p_ssoButtonTitle_get: return "[get] .ssoButtonTitle" - case .p_oAuthClientId_get: return "[get] .oAuthClientId" - case .p_tokenType_get: return "[get] .tokenType" - case .p_feedbackEmail_get: return "[get] .feedbackEmail" - case .p_appStoreLink_get: return "[get] .appStoreLink" - case .p_faq_get: return "[get] .faq" - case .p_platformName_get: return "[get] .platformName" - case .p_agreement_get: return "[get] .agreement" - case .p_firebase_get: return "[get] .firebase" - case .p_facebook_get: return "[get] .facebook" - case .p_microsoft_get: return "[get] .microsoft" - case .p_google_get: return "[get] .google" - case .p_appleSignIn_get: return "[get] .appleSignIn" - case .p_features_get: return "[get] .features" - case .p_theme_get: return "[get] .theme" - case .p_uiComponents_get: return "[get] .uiComponents" - case .p_discovery_get: return "[get] .discovery" - case .p_dashboard_get: return "[get] .dashboard" - case .p_braze_get: return "[get] .braze" - case .p_branch_get: return "[get] .branch" - case .p_program_get: return "[get] .program" - case .p_experimentalFeatures_get: return "[get] .experimentalFeatures" - case .p_URIScheme_get: return "[get] .URIScheme" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func baseURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func baseSSOURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseSSOURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoFinishedURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_ssoFinishedURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoButtonTitle(getter defaultValue: [String: Any]...) -> PropertyStub { - return Given(method: .p_ssoButtonTitle_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func oAuthClientId(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_oAuthClientId_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func tokenType(getter defaultValue: TokenType...) -> PropertyStub { - return Given(method: .p_tokenType_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func feedbackEmail(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_feedbackEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appStoreLink(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_appStoreLink_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func faq(getter defaultValue: URL?...) -> PropertyStub { - return Given(method: .p_faq_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func platformName(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_platformName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func agreement(getter defaultValue: AgreementConfig...) -> PropertyStub { - return Given(method: .p_agreement_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func firebase(getter defaultValue: FirebaseConfig...) -> PropertyStub { - return Given(method: .p_firebase_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func facebook(getter defaultValue: FacebookConfig...) -> PropertyStub { - return Given(method: .p_facebook_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func microsoft(getter defaultValue: MicrosoftConfig...) -> PropertyStub { - return Given(method: .p_microsoft_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func google(getter defaultValue: GoogleConfig...) -> PropertyStub { - return Given(method: .p_google_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignIn(getter defaultValue: AppleSignInConfig...) -> PropertyStub { - return Given(method: .p_appleSignIn_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func features(getter defaultValue: FeaturesConfig...) -> PropertyStub { - return Given(method: .p_features_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func theme(getter defaultValue: ThemeConfig...) -> PropertyStub { - return Given(method: .p_theme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func uiComponents(getter defaultValue: UIComponentsConfig...) -> PropertyStub { - return Given(method: .p_uiComponents_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func discovery(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_discovery_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func dashboard(getter defaultValue: DashboardConfig...) -> PropertyStub { - return Given(method: .p_dashboard_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func braze(getter defaultValue: BrazeConfig...) -> PropertyStub { - return Given(method: .p_braze_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func branch(getter defaultValue: BranchConfig...) -> PropertyStub { - return Given(method: .p_branch_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func program(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_program_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func experimentalFeatures(getter defaultValue: ExperimentalFeaturesConfig...) -> PropertyStub { - return Given(method: .p_experimentalFeatures_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func URIScheme(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_URIScheme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var baseURL: Verify { return Verify(method: .p_baseURL_get) } - public static var baseSSOURL: Verify { return Verify(method: .p_baseSSOURL_get) } - public static var ssoFinishedURL: Verify { return Verify(method: .p_ssoFinishedURL_get) } - public static var ssoButtonTitle: Verify { return Verify(method: .p_ssoButtonTitle_get) } - public static var oAuthClientId: Verify { return Verify(method: .p_oAuthClientId_get) } - public static var tokenType: Verify { return Verify(method: .p_tokenType_get) } - public static var feedbackEmail: Verify { return Verify(method: .p_feedbackEmail_get) } - public static var appStoreLink: Verify { return Verify(method: .p_appStoreLink_get) } - public static var faq: Verify { return Verify(method: .p_faq_get) } - public static var platformName: Verify { return Verify(method: .p_platformName_get) } - public static var agreement: Verify { return Verify(method: .p_agreement_get) } - public static var firebase: Verify { return Verify(method: .p_firebase_get) } - public static var facebook: Verify { return Verify(method: .p_facebook_get) } - public static var microsoft: Verify { return Verify(method: .p_microsoft_get) } - public static var google: Verify { return Verify(method: .p_google_get) } - public static var appleSignIn: Verify { return Verify(method: .p_appleSignIn_get) } - public static var features: Verify { return Verify(method: .p_features_get) } - public static var theme: Verify { return Verify(method: .p_theme_get) } - public static var uiComponents: Verify { return Verify(method: .p_uiComponents_get) } - public static var discovery: Verify { return Verify(method: .p_discovery_get) } - public static var dashboard: Verify { return Verify(method: .p_dashboard_get) } - public static var braze: Verify { return Verify(method: .p_braze_get) } - public static var branch: Verify { return Verify(method: .p_branch_get) } - public static var program: Verify { return Verify(method: .p_program_get) } - public static var experimentalFeatures: Verify { return Verify(method: .p_experimentalFeatures_get) } - public static var URIScheme: Verify { return Verify(method: .p_URIScheme_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConnectivityProtocol -@MainActor -open class ConnectivityProtocolMock: ConnectivityProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var isInternetAvaliable: Bool { - get { invocations.append(.p_isInternetAvaliable_get); return __p_isInternetAvaliable ?? givenGetterValue(.p_isInternetAvaliable_get, "ConnectivityProtocolMock - stub value for isInternetAvaliable was not defined") } - } - private var __p_isInternetAvaliable: (Bool)? - - public var isMobileData: Bool { - get { invocations.append(.p_isMobileData_get); return __p_isMobileData ?? givenGetterValue(.p_isMobileData_get, "ConnectivityProtocolMock - stub value for isMobileData was not defined") } - } - private var __p_isMobileData: (Bool)? - - public var internetReachableSubject: CurrentValueSubject { - get { invocations.append(.p_internetReachableSubject_get); return __p_internetReachableSubject ?? givenGetterValue(.p_internetReachableSubject_get, "ConnectivityProtocolMock - stub value for internetReachableSubject was not defined") } - } - private var __p_internetReachableSubject: (CurrentValueSubject)? - - - - - - - fileprivate enum MethodType { - case p_isInternetAvaliable_get - case p_isMobileData_get - case p_internetReachableSubject_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_isInternetAvaliable_get,.p_isInternetAvaliable_get): return Matcher.ComparisonResult.match - case (.p_isMobileData_get,.p_isMobileData_get): return Matcher.ComparisonResult.match - case (.p_internetReachableSubject_get,.p_internetReachableSubject_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_isInternetAvaliable_get: return 0 - case .p_isMobileData_get: return 0 - case .p_internetReachableSubject_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_isInternetAvaliable_get: return "[get] .isInternetAvaliable" - case .p_isMobileData_get: return "[get] .isMobileData" - case .p_internetReachableSubject_get: return "[get] .internetReachableSubject" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func isInternetAvaliable(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isInternetAvaliable_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func isMobileData(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isMobileData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func internetReachableSubject(getter defaultValue: CurrentValueSubject...) -> PropertyStub { - return Given(method: .p_internetReachableSubject_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var isInternetAvaliable: Verify { return Verify(method: .p_isInternetAvaliable_get) } - public static var isMobileData: Verify { return Verify(method: .p_isMobileData_get) } - public static var internetReachableSubject: Verify { return Verify(method: .p_internetReachableSubject_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreAnalytics - -open class CoreAnalyticsMock: CoreAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { - addInvocation(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) - let perform = methodPerformValue(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) as? (AnalyticsEvent, EventBIValue, String?, Int?) -> Void - perform?(`event`, `biValue`, `action`, `rating`) - } - - open func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { - addInvocation(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) - let perform = methodPerformValue(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) as? (AnalyticsEvent, EventBIValue, String, String) -> Void - perform?(`event`, `bivalue`, `value`, `oldValue`) - } - - open func trackEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackScreenEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackScreenEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - - fileprivate enum MethodType { - case m_trackEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter, Parameter, Parameter, Parameter) - case m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter, Parameter, Parameter, Parameter) - case m_trackEvent__event(Parameter) - case m_trackEvent__eventbiValue_biValue(Parameter, Parameter) - case m_trackScreenEvent__event(Parameter) - case m_trackScreenEvent__eventbiValue_biValue(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_trackEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackScreenEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_appreview__eventbiValue_biValueaction_actionrating_rating(let lhsEvent, let lhsBivalue, let lhsAction, let lhsRating), .m_appreview__eventbiValue_biValueaction_actionrating_rating(let rhsEvent, let rhsBivalue, let rhsAction, let rhsRating)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRating, rhs: rhsRating, with: matcher), lhsRating, rhsRating, "rating")) - return Matcher.ComparisonResult(results) - - case (.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let lhsEvent, let lhsBivalue, let lhsValue, let lhsOldvalue), .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let rhsEvent, let rhsBivalue, let rhsValue, let rhsOldvalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "bivalue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsValue, rhs: rhsValue, with: matcher), lhsValue, rhsValue, "value")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOldvalue, rhs: rhsOldvalue, with: matcher), lhsOldvalue, rhsOldvalue, "oldValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__event(let lhsEvent), .m_trackEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__event(let lhsEvent), .m_trackScreenEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackScreenEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_trackEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_trackScreenEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_appreview__eventbiValue_biValueaction_actionrating_rating(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_trackEvent__event(p0): return p0.intValue - case let .m_trackEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__event(p0): return p0.intValue - case let .m_trackScreenEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_trackEvent__eventparameters_parameters: return ".trackEvent(_:parameters:)" - case .m_trackEvent__eventbiValue_biValueparameters_parameters: return ".trackEvent(_:biValue:parameters:)" - case .m_trackScreenEvent__eventparameters_parameters: return ".trackScreenEvent(_:parameters:)" - case .m_trackScreenEvent__eventbiValue_biValueparameters_parameters: return ".trackScreenEvent(_:biValue:parameters:)" - case .m_appreview__eventbiValue_biValueaction_actionrating_rating: return ".appreview(_:biValue:action:rating:)" - case .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue: return ".videoQualityChanged(_:bivalue:value:oldValue:)" - case .m_trackEvent__event: return ".trackEvent(_:)" - case .m_trackEvent__eventbiValue_biValue: return ".trackEvent(_:biValue:)" - case .m_trackScreenEvent__event: return ".trackScreenEvent(_:)" - case .m_trackScreenEvent__eventbiValue_biValue: return ".trackScreenEvent(_:biValue:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter) -> Verify { return Verify(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`))} - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter) -> Verify { return Verify(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`))} - public static func trackEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackEvent__event(`event`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`))} - public static func trackScreenEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__event(`event`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String?, Int?) -> Void) -> Perform { - return Perform(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`), performs: perform) - } - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String, String) -> Void) -> Perform { - return Perform(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`), performs: perform) - } - public static func trackEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackEvent__event(`event`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__event(`event`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CorePersistenceProtocol - -open class CorePersistenceProtocolMock: CorePersistenceProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func set(userId: Int) { - addInvocation(.m_set__userId_userId(Parameter.value(`userId`))) - let perform = methodPerformValue(.m_set__userId_userId(Parameter.value(`userId`))) as? (Int) -> Void - perform?(`userId`) - } - - open func getUserID() -> Int? { - addInvocation(.m_getUserID) - let perform = methodPerformValue(.m_getUserID) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getUserID).casted() - } catch { - // do nothing - } - return __value - } - - @MainActor - open func publisher() throws -> AnyPublisher { - addInvocation(.m_publisher) - let perform = methodPerformValue(.m_publisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_publisher).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for publisher(). Use given") - Failure("Stub return value not specified for publisher(). Use given") - } catch { - throw error - } - return __value - } - - open func addToDownloadQueue(tasks: [DownloadDataTask]) { - addInvocation(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) as? ([DownloadDataTask]) -> Void - perform?(`tasks`) - } - - open func saveOfflineProgress(progress: OfflineProgress) { - addInvocation(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) - let perform = methodPerformValue(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) as? (OfflineProgress) -> Void - perform?(`progress`) - } - - open func loadProgress(for blockID: String) -> OfflineProgress? { - addInvocation(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - var __value: OfflineProgress? = nil - do { - __value = try methodReturnValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))).casted() - } catch { - // do nothing - } - return __value - } - - open func loadAllOfflineProgress() -> [OfflineProgress] { - addInvocation(.m_loadAllOfflineProgress) - let perform = methodPerformValue(.m_loadAllOfflineProgress) as? () -> Void - perform?() - var __value: [OfflineProgress] - do { - __value = try methodReturnValue(.m_loadAllOfflineProgress).casted() - } catch { - onFatalFailure("Stub return value not specified for loadAllOfflineProgress(). Use given") - Failure("Stub return value not specified for loadAllOfflineProgress(). Use given") - } - return __value - } - - open func deleteProgress(for blockID: String) { - addInvocation(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - } - - open func deleteAllProgress() { - addInvocation(.m_deleteAllProgress) - let perform = methodPerformValue(.m_deleteAllProgress) as? () -> Void - perform?() - } - - open func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { - addInvocation(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) as? ([CourseBlock], DownloadQuality) -> Void - perform?(`blocks`, `downloadQuality`) - } - - open func updateTask(task: DownloadDataTask) { - addInvocation(.m_updateTask__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_updateTask__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - } - - open func downloadDataTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getDownloadDataTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasks) - let perform = methodPerformValue(.m_getDownloadDataTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasks(). Use given") - Failure("Stub return value not specified for getDownloadDataTasks(). Use given") - } - return __value - } - - open func getDownloadDataTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func deleteDownloadDataTasks(ids: [String]) { - addInvocation(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) - let perform = methodPerformValue(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) as? ([String]) -> Void - perform?(`ids`) - } - - - fileprivate enum MethodType { - case m_set__userId_userId(Parameter) - case m_getUserID - case m_publisher - case m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>) - case m_saveOfflineProgress__progress_progress(Parameter) - case m_loadProgress__for_blockID(Parameter) - case m_loadAllOfflineProgress - case m_deleteProgress__for_blockID(Parameter) - case m_deleteAllProgress - case m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>, Parameter) - case m_updateTask__task_task(Parameter) - case m_downloadDataTask__for_blockId(Parameter) - case m_getDownloadDataTasks - case m_getDownloadDataTasksForCourse__courseId(Parameter) - case m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_set__userId_userId(let lhsUserid), .m_set__userId_userId(let rhsUserid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUserid, rhs: rhsUserid, with: matcher), lhsUserid, rhsUserid, "userId")) - return Matcher.ComparisonResult(results) - - case (.m_getUserID, .m_getUserID): return .match - - case (.m_publisher, .m_publisher): return .match - - case (.m_addToDownloadQueue__tasks_tasks(let lhsTasks), .m_addToDownloadQueue__tasks_tasks(let rhsTasks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTasks, rhs: rhsTasks, with: matcher), lhsTasks, rhsTasks, "tasks")) - return Matcher.ComparisonResult(results) - - case (.m_saveOfflineProgress__progress_progress(let lhsProgress), .m_saveOfflineProgress__progress_progress(let rhsProgress)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsProgress, rhs: rhsProgress, with: matcher), lhsProgress, rhsProgress, "progress")) - return Matcher.ComparisonResult(results) - - case (.m_loadProgress__for_blockID(let lhsBlockid), .m_loadProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_loadAllOfflineProgress, .m_loadAllOfflineProgress): return .match - - case (.m_deleteProgress__for_blockID(let lhsBlockid), .m_deleteProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_deleteAllProgress, .m_deleteAllProgress): return .match - - case (.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let lhsBlocks, let lhsDownloadquality), .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let rhsBlocks, let rhsDownloadquality)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadquality, rhs: rhsDownloadquality, with: matcher), lhsDownloadquality, rhsDownloadquality, "downloadQuality")) - return Matcher.ComparisonResult(results) - - case (.m_updateTask__task_task(let lhsTask), .m_updateTask__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_downloadDataTask__for_blockId(let lhsBlockid), .m_downloadDataTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadDataTasks, .m_getDownloadDataTasks): return .match - - case (.m_getDownloadDataTasksForCourse__courseId(let lhsCourseid), .m_getDownloadDataTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_deleteDownloadDataTasks__ids_ids(let lhsIds), .m_deleteDownloadDataTasks__ids_ids(let rhsIds)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIds, rhs: rhsIds, with: matcher), lhsIds, rhsIds, "ids")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_set__userId_userId(p0): return p0.intValue - case .m_getUserID: return 0 - case .m_publisher: return 0 - case let .m_addToDownloadQueue__tasks_tasks(p0): return p0.intValue - case let .m_saveOfflineProgress__progress_progress(p0): return p0.intValue - case let .m_loadProgress__for_blockID(p0): return p0.intValue - case .m_loadAllOfflineProgress: return 0 - case let .m_deleteProgress__for_blockID(p0): return p0.intValue - case .m_deleteAllProgress: return 0 - case let .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(p0, p1): return p0.intValue + p1.intValue - case let .m_updateTask__task_task(p0): return p0.intValue - case let .m_downloadDataTask__for_blockId(p0): return p0.intValue - case .m_getDownloadDataTasks: return 0 - case let .m_getDownloadDataTasksForCourse__courseId(p0): return p0.intValue - case let .m_deleteDownloadDataTasks__ids_ids(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_set__userId_userId: return ".set(userId:)" - case .m_getUserID: return ".getUserID()" - case .m_publisher: return ".publisher()" - case .m_addToDownloadQueue__tasks_tasks: return ".addToDownloadQueue(tasks:)" - case .m_saveOfflineProgress__progress_progress: return ".saveOfflineProgress(progress:)" - case .m_loadProgress__for_blockID: return ".loadProgress(for:)" - case .m_loadAllOfflineProgress: return ".loadAllOfflineProgress()" - case .m_deleteProgress__for_blockID: return ".deleteProgress(for:)" - case .m_deleteAllProgress: return ".deleteAllProgress()" - case .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality: return ".addToDownloadQueue(blocks:downloadQuality:)" - case .m_updateTask__task_task: return ".updateTask(task:)" - case .m_downloadDataTask__for_blockId: return ".downloadDataTask(for:)" - case .m_getDownloadDataTasks: return ".getDownloadDataTasks()" - case .m_getDownloadDataTasksForCourse__courseId: return ".getDownloadDataTasksForCourse(_:)" - case .m_deleteDownloadDataTasks__ids_ids: return ".deleteDownloadDataTasks(ids:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getUserID(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @MainActor - public static func publisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_publisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadProgress(for blockID: Parameter, willReturn: OfflineProgress?...) -> MethodStub { - return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadAllOfflineProgress(willReturn: [OfflineProgress]...) -> MethodStub { - return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadDataTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getUserID(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func loadProgress(for blockID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [OfflineProgress?] = [] - let given: Given = { return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (OfflineProgress?).self) - willProduce(stubber) - return given - } - public static func loadAllOfflineProgress(willProduce: (Stubber<[OfflineProgress]>) -> Void) -> MethodStub { - let willReturn: [[OfflineProgress]] = [] - let given: Given = { return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([OfflineProgress]).self) - willProduce(stubber) - return given - } - public static func downloadDataTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - @MainActor - public static func publisher(willThrow: Error...) -> MethodStub { - return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) - } - @MainActor - public static func publisher(willProduce: (StubberThrows>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func set(userId: Parameter) -> Verify { return Verify(method: .m_set__userId_userId(`userId`))} - public static func getUserID() -> Verify { return Verify(method: .m_getUserID)} - @MainActor - public static func publisher() -> Verify { return Verify(method: .m_publisher)} - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>) -> Verify { return Verify(method: .m_addToDownloadQueue__tasks_tasks(`tasks`))} - public static func saveOfflineProgress(progress: Parameter) -> Verify { return Verify(method: .m_saveOfflineProgress__progress_progress(`progress`))} - public static func loadProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_loadProgress__for_blockID(`blockID`))} - public static func loadAllOfflineProgress() -> Verify { return Verify(method: .m_loadAllOfflineProgress)} - public static func deleteProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_deleteProgress__for_blockID(`blockID`))} - public static func deleteAllProgress() -> Verify { return Verify(method: .m_deleteAllProgress)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`))} - public static func updateTask(task: Parameter) -> Verify { return Verify(method: .m_updateTask__task_task(`task`))} - public static func downloadDataTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadDataTask__for_blockId(`blockId`))} - public static func getDownloadDataTasks() -> Verify { return Verify(method: .m_getDownloadDataTasks)} - public static func getDownloadDataTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`))} - public static func deleteDownloadDataTasks(ids: Parameter<[String]>) -> Verify { return Verify(method: .m_deleteDownloadDataTasks__ids_ids(`ids`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func set(userId: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_set__userId_userId(`userId`), performs: perform) - } - public static func getUserID(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getUserID, performs: perform) - } - @MainActor - public static func publisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_publisher, performs: perform) - } - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>, perform: @escaping ([DownloadDataTask]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__tasks_tasks(`tasks`), performs: perform) - } - public static func saveOfflineProgress(progress: Parameter, perform: @escaping (OfflineProgress) -> Void) -> Perform { - return Perform(method: .m_saveOfflineProgress__progress_progress(`progress`), performs: perform) - } - public static func loadProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_loadProgress__for_blockID(`blockID`), performs: perform) - } - public static func loadAllOfflineProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_loadAllOfflineProgress, performs: perform) - } - public static func deleteProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_deleteProgress__for_blockID(`blockID`), performs: perform) - } - public static func deleteAllProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAllProgress, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter, perform: @escaping ([CourseBlock], DownloadQuality) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`), performs: perform) - } - public static func updateTask(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_updateTask__task_task(`task`), performs: perform) - } - public static func downloadDataTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadDataTask__for_blockId(`blockId`), performs: perform) - } - public static func getDownloadDataTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasks, performs: perform) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func deleteDownloadDataTasks(ids: Parameter<[String]>, perform: @escaping ([String]) -> Void) -> Perform { - return Perform(method: .m_deleteDownloadDataTasks__ids_ids(`ids`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreStorage - -open class CoreStorageMock: CoreStorage, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var accessToken: String? { - get { invocations.append(.p_accessToken_get); return __p_accessToken ?? optionalGivenGetterValue(.p_accessToken_get, "CoreStorageMock - stub value for accessToken was not defined") } - set { invocations.append(.p_accessToken_set(.value(newValue))); __p_accessToken = newValue } - } - private var __p_accessToken: (String)? - - public var refreshToken: String? { - get { invocations.append(.p_refreshToken_get); return __p_refreshToken ?? optionalGivenGetterValue(.p_refreshToken_get, "CoreStorageMock - stub value for refreshToken was not defined") } - set { invocations.append(.p_refreshToken_set(.value(newValue))); __p_refreshToken = newValue } - } - private var __p_refreshToken: (String)? - - public var pushToken: String? { - get { invocations.append(.p_pushToken_get); return __p_pushToken ?? optionalGivenGetterValue(.p_pushToken_get, "CoreStorageMock - stub value for pushToken was not defined") } - set { invocations.append(.p_pushToken_set(.value(newValue))); __p_pushToken = newValue } - } - private var __p_pushToken: (String)? - - public var appleSignFullName: String? { - get { invocations.append(.p_appleSignFullName_get); return __p_appleSignFullName ?? optionalGivenGetterValue(.p_appleSignFullName_get, "CoreStorageMock - stub value for appleSignFullName was not defined") } - set { invocations.append(.p_appleSignFullName_set(.value(newValue))); __p_appleSignFullName = newValue } - } - private var __p_appleSignFullName: (String)? - - public var appleSignEmail: String? { - get { invocations.append(.p_appleSignEmail_get); return __p_appleSignEmail ?? optionalGivenGetterValue(.p_appleSignEmail_get, "CoreStorageMock - stub value for appleSignEmail was not defined") } - set { invocations.append(.p_appleSignEmail_set(.value(newValue))); __p_appleSignEmail = newValue } - } - private var __p_appleSignEmail: (String)? - - public var cookiesDate: Date? { - get { invocations.append(.p_cookiesDate_get); return __p_cookiesDate ?? optionalGivenGetterValue(.p_cookiesDate_get, "CoreStorageMock - stub value for cookiesDate was not defined") } - set { invocations.append(.p_cookiesDate_set(.value(newValue))); __p_cookiesDate = newValue } - } - private var __p_cookiesDate: (Date)? - - public var reviewLastShownVersion: String? { - get { invocations.append(.p_reviewLastShownVersion_get); return __p_reviewLastShownVersion ?? optionalGivenGetterValue(.p_reviewLastShownVersion_get, "CoreStorageMock - stub value for reviewLastShownVersion was not defined") } - set { invocations.append(.p_reviewLastShownVersion_set(.value(newValue))); __p_reviewLastShownVersion = newValue } - } - private var __p_reviewLastShownVersion: (String)? - - public var lastReviewDate: Date? { - get { invocations.append(.p_lastReviewDate_get); return __p_lastReviewDate ?? optionalGivenGetterValue(.p_lastReviewDate_get, "CoreStorageMock - stub value for lastReviewDate was not defined") } - set { invocations.append(.p_lastReviewDate_set(.value(newValue))); __p_lastReviewDate = newValue } - } - private var __p_lastReviewDate: (Date)? - - public var user: DataLayer.User? { - get { invocations.append(.p_user_get); return __p_user ?? optionalGivenGetterValue(.p_user_get, "CoreStorageMock - stub value for user was not defined") } - set { invocations.append(.p_user_set(.value(newValue))); __p_user = newValue } - } - private var __p_user: (DataLayer.User)? - - public var userSettings: UserSettings? { - get { invocations.append(.p_userSettings_get); return __p_userSettings ?? optionalGivenGetterValue(.p_userSettings_get, "CoreStorageMock - stub value for userSettings was not defined") } - set { invocations.append(.p_userSettings_set(.value(newValue))); __p_userSettings = newValue } - } - private var __p_userSettings: (UserSettings)? - - public var resetAppSupportDirectoryUserData: Bool? { - get { invocations.append(.p_resetAppSupportDirectoryUserData_get); return __p_resetAppSupportDirectoryUserData ?? optionalGivenGetterValue(.p_resetAppSupportDirectoryUserData_get, "CoreStorageMock - stub value for resetAppSupportDirectoryUserData was not defined") } - set { invocations.append(.p_resetAppSupportDirectoryUserData_set(.value(newValue))); __p_resetAppSupportDirectoryUserData = newValue } - } - private var __p_resetAppSupportDirectoryUserData: (Bool)? - - public var useRelativeDates: Bool { - get { invocations.append(.p_useRelativeDates_get); return __p_useRelativeDates ?? givenGetterValue(.p_useRelativeDates_get, "CoreStorageMock - stub value for useRelativeDates was not defined") } - set { invocations.append(.p_useRelativeDates_set(.value(newValue))); __p_useRelativeDates = newValue } - } - private var __p_useRelativeDates: (Bool)? - - public var lastUsedSocialAuth: String? { - get { invocations.append(.p_lastUsedSocialAuth_get); return __p_lastUsedSocialAuth ?? optionalGivenGetterValue(.p_lastUsedSocialAuth_get, "CoreStorageMock - stub value for lastUsedSocialAuth was not defined") } - set { invocations.append(.p_lastUsedSocialAuth_set(.value(newValue))); __p_lastUsedSocialAuth = newValue } - } - private var __p_lastUsedSocialAuth: (String)? - - public var latestAvailableAppVersion: String? { - get { invocations.append(.p_latestAvailableAppVersion_get); return __p_latestAvailableAppVersion ?? optionalGivenGetterValue(.p_latestAvailableAppVersion_get, "CoreStorageMock - stub value for latestAvailableAppVersion was not defined") } - set { invocations.append(.p_latestAvailableAppVersion_set(.value(newValue))); __p_latestAvailableAppVersion = newValue } - } - private var __p_latestAvailableAppVersion: (String)? - - public var updateAppRequired: Bool { - get { invocations.append(.p_updateAppRequired_get); return __p_updateAppRequired ?? givenGetterValue(.p_updateAppRequired_get, "CoreStorageMock - stub value for updateAppRequired was not defined") } - set { invocations.append(.p_updateAppRequired_set(.value(newValue))); __p_updateAppRequired = newValue } - } - private var __p_updateAppRequired: (Bool)? - - - - - - open func clear() { - addInvocation(.m_clear) - let perform = methodPerformValue(.m_clear) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_clear - case p_accessToken_get - case p_accessToken_set(Parameter) - case p_refreshToken_get - case p_refreshToken_set(Parameter) - case p_pushToken_get - case p_pushToken_set(Parameter) - case p_appleSignFullName_get - case p_appleSignFullName_set(Parameter) - case p_appleSignEmail_get - case p_appleSignEmail_set(Parameter) - case p_cookiesDate_get - case p_cookiesDate_set(Parameter) - case p_reviewLastShownVersion_get - case p_reviewLastShownVersion_set(Parameter) - case p_lastReviewDate_get - case p_lastReviewDate_set(Parameter) - case p_user_get - case p_user_set(Parameter) - case p_userSettings_get - case p_userSettings_set(Parameter) - case p_resetAppSupportDirectoryUserData_get - case p_resetAppSupportDirectoryUserData_set(Parameter) - case p_useRelativeDates_get - case p_useRelativeDates_set(Parameter) - case p_lastUsedSocialAuth_get - case p_lastUsedSocialAuth_set(Parameter) - case p_latestAvailableAppVersion_get - case p_latestAvailableAppVersion_set(Parameter) - case p_updateAppRequired_get - case p_updateAppRequired_set(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_clear, .m_clear): return .match - case (.p_accessToken_get,.p_accessToken_get): return Matcher.ComparisonResult.match - case (.p_accessToken_set(let left),.p_accessToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_refreshToken_get,.p_refreshToken_get): return Matcher.ComparisonResult.match - case (.p_refreshToken_set(let left),.p_refreshToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_pushToken_get,.p_pushToken_get): return Matcher.ComparisonResult.match - case (.p_pushToken_set(let left),.p_pushToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignFullName_get,.p_appleSignFullName_get): return Matcher.ComparisonResult.match - case (.p_appleSignFullName_set(let left),.p_appleSignFullName_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignEmail_get,.p_appleSignEmail_get): return Matcher.ComparisonResult.match - case (.p_appleSignEmail_set(let left),.p_appleSignEmail_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_cookiesDate_get,.p_cookiesDate_get): return Matcher.ComparisonResult.match - case (.p_cookiesDate_set(let left),.p_cookiesDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_reviewLastShownVersion_get,.p_reviewLastShownVersion_get): return Matcher.ComparisonResult.match - case (.p_reviewLastShownVersion_set(let left),.p_reviewLastShownVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastReviewDate_get,.p_lastReviewDate_get): return Matcher.ComparisonResult.match - case (.p_lastReviewDate_set(let left),.p_lastReviewDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_user_get,.p_user_get): return Matcher.ComparisonResult.match - case (.p_user_set(let left),.p_user_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_userSettings_get,.p_userSettings_get): return Matcher.ComparisonResult.match - case (.p_userSettings_set(let left),.p_userSettings_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_resetAppSupportDirectoryUserData_get,.p_resetAppSupportDirectoryUserData_get): return Matcher.ComparisonResult.match - case (.p_resetAppSupportDirectoryUserData_set(let left),.p_resetAppSupportDirectoryUserData_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_useRelativeDates_get,.p_useRelativeDates_get): return Matcher.ComparisonResult.match - case (.p_useRelativeDates_set(let left),.p_useRelativeDates_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastUsedSocialAuth_get,.p_lastUsedSocialAuth_get): return Matcher.ComparisonResult.match - case (.p_lastUsedSocialAuth_set(let left),.p_lastUsedSocialAuth_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_latestAvailableAppVersion_get,.p_latestAvailableAppVersion_get): return Matcher.ComparisonResult.match - case (.p_latestAvailableAppVersion_set(let left),.p_latestAvailableAppVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_updateAppRequired_get,.p_updateAppRequired_get): return Matcher.ComparisonResult.match - case (.p_updateAppRequired_set(let left),.p_updateAppRequired_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_clear: return 0 - case .p_accessToken_get: return 0 - case .p_accessToken_set(let newValue): return newValue.intValue - case .p_refreshToken_get: return 0 - case .p_refreshToken_set(let newValue): return newValue.intValue - case .p_pushToken_get: return 0 - case .p_pushToken_set(let newValue): return newValue.intValue - case .p_appleSignFullName_get: return 0 - case .p_appleSignFullName_set(let newValue): return newValue.intValue - case .p_appleSignEmail_get: return 0 - case .p_appleSignEmail_set(let newValue): return newValue.intValue - case .p_cookiesDate_get: return 0 - case .p_cookiesDate_set(let newValue): return newValue.intValue - case .p_reviewLastShownVersion_get: return 0 - case .p_reviewLastShownVersion_set(let newValue): return newValue.intValue - case .p_lastReviewDate_get: return 0 - case .p_lastReviewDate_set(let newValue): return newValue.intValue - case .p_user_get: return 0 - case .p_user_set(let newValue): return newValue.intValue - case .p_userSettings_get: return 0 - case .p_userSettings_set(let newValue): return newValue.intValue - case .p_resetAppSupportDirectoryUserData_get: return 0 - case .p_resetAppSupportDirectoryUserData_set(let newValue): return newValue.intValue - case .p_useRelativeDates_get: return 0 - case .p_useRelativeDates_set(let newValue): return newValue.intValue - case .p_lastUsedSocialAuth_get: return 0 - case .p_lastUsedSocialAuth_set(let newValue): return newValue.intValue - case .p_latestAvailableAppVersion_get: return 0 - case .p_latestAvailableAppVersion_set(let newValue): return newValue.intValue - case .p_updateAppRequired_get: return 0 - case .p_updateAppRequired_set(let newValue): return newValue.intValue - } - } - func assertionName() -> String { - switch self { - case .m_clear: return ".clear()" - case .p_accessToken_get: return "[get] .accessToken" - case .p_accessToken_set: return "[set] .accessToken" - case .p_refreshToken_get: return "[get] .refreshToken" - case .p_refreshToken_set: return "[set] .refreshToken" - case .p_pushToken_get: return "[get] .pushToken" - case .p_pushToken_set: return "[set] .pushToken" - case .p_appleSignFullName_get: return "[get] .appleSignFullName" - case .p_appleSignFullName_set: return "[set] .appleSignFullName" - case .p_appleSignEmail_get: return "[get] .appleSignEmail" - case .p_appleSignEmail_set: return "[set] .appleSignEmail" - case .p_cookiesDate_get: return "[get] .cookiesDate" - case .p_cookiesDate_set: return "[set] .cookiesDate" - case .p_reviewLastShownVersion_get: return "[get] .reviewLastShownVersion" - case .p_reviewLastShownVersion_set: return "[set] .reviewLastShownVersion" - case .p_lastReviewDate_get: return "[get] .lastReviewDate" - case .p_lastReviewDate_set: return "[set] .lastReviewDate" - case .p_user_get: return "[get] .user" - case .p_user_set: return "[set] .user" - case .p_userSettings_get: return "[get] .userSettings" - case .p_userSettings_set: return "[set] .userSettings" - case .p_resetAppSupportDirectoryUserData_get: return "[get] .resetAppSupportDirectoryUserData" - case .p_resetAppSupportDirectoryUserData_set: return "[set] .resetAppSupportDirectoryUserData" - case .p_useRelativeDates_get: return "[get] .useRelativeDates" - case .p_useRelativeDates_set: return "[set] .useRelativeDates" - case .p_lastUsedSocialAuth_get: return "[get] .lastUsedSocialAuth" - case .p_lastUsedSocialAuth_set: return "[set] .lastUsedSocialAuth" - case .p_latestAvailableAppVersion_get: return "[get] .latestAvailableAppVersion" - case .p_latestAvailableAppVersion_set: return "[set] .latestAvailableAppVersion" - case .p_updateAppRequired_get: return "[get] .updateAppRequired" - case .p_updateAppRequired_set: return "[set] .updateAppRequired" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func accessToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_accessToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func refreshToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_refreshToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func pushToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_pushToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignFullName(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignFullName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignEmail(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func cookiesDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_cookiesDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func reviewLastShownVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_reviewLastShownVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastReviewDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_lastReviewDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func user(getter defaultValue: DataLayer.User?...) -> PropertyStub { - return Given(method: .p_user_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func userSettings(getter defaultValue: UserSettings?...) -> PropertyStub { - return Given(method: .p_userSettings_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func resetAppSupportDirectoryUserData(getter defaultValue: Bool?...) -> PropertyStub { - return Given(method: .p_resetAppSupportDirectoryUserData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func useRelativeDates(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_useRelativeDates_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastUsedSocialAuth(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_lastUsedSocialAuth_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func latestAvailableAppVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_latestAvailableAppVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func updateAppRequired(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_updateAppRequired_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func clear() -> Verify { return Verify(method: .m_clear)} - public static var accessToken: Verify { return Verify(method: .p_accessToken_get) } - public static func accessToken(set newValue: Parameter) -> Verify { return Verify(method: .p_accessToken_set(newValue)) } - public static var refreshToken: Verify { return Verify(method: .p_refreshToken_get) } - public static func refreshToken(set newValue: Parameter) -> Verify { return Verify(method: .p_refreshToken_set(newValue)) } - public static var pushToken: Verify { return Verify(method: .p_pushToken_get) } - public static func pushToken(set newValue: Parameter) -> Verify { return Verify(method: .p_pushToken_set(newValue)) } - public static var appleSignFullName: Verify { return Verify(method: .p_appleSignFullName_get) } - public static func appleSignFullName(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignFullName_set(newValue)) } - public static var appleSignEmail: Verify { return Verify(method: .p_appleSignEmail_get) } - public static func appleSignEmail(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignEmail_set(newValue)) } - public static var cookiesDate: Verify { return Verify(method: .p_cookiesDate_get) } - public static func cookiesDate(set newValue: Parameter) -> Verify { return Verify(method: .p_cookiesDate_set(newValue)) } - public static var reviewLastShownVersion: Verify { return Verify(method: .p_reviewLastShownVersion_get) } - public static func reviewLastShownVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_reviewLastShownVersion_set(newValue)) } - public static var lastReviewDate: Verify { return Verify(method: .p_lastReviewDate_get) } - public static func lastReviewDate(set newValue: Parameter) -> Verify { return Verify(method: .p_lastReviewDate_set(newValue)) } - public static var user: Verify { return Verify(method: .p_user_get) } - public static func user(set newValue: Parameter) -> Verify { return Verify(method: .p_user_set(newValue)) } - public static var userSettings: Verify { return Verify(method: .p_userSettings_get) } - public static func userSettings(set newValue: Parameter) -> Verify { return Verify(method: .p_userSettings_set(newValue)) } - public static var resetAppSupportDirectoryUserData: Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_get) } - public static func resetAppSupportDirectoryUserData(set newValue: Parameter) -> Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_set(newValue)) } - public static var useRelativeDates: Verify { return Verify(method: .p_useRelativeDates_get) } - public static func useRelativeDates(set newValue: Parameter) -> Verify { return Verify(method: .p_useRelativeDates_set(newValue)) } - public static var lastUsedSocialAuth: Verify { return Verify(method: .p_lastUsedSocialAuth_get) } - public static func lastUsedSocialAuth(set newValue: Parameter) -> Verify { return Verify(method: .p_lastUsedSocialAuth_set(newValue)) } - public static var latestAvailableAppVersion: Verify { return Verify(method: .p_latestAvailableAppVersion_get) } - public static func latestAvailableAppVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_latestAvailableAppVersion_set(newValue)) } - public static var updateAppRequired: Verify { return Verify(method: .p_updateAppRequired_get) } - public static func updateAppRequired(set newValue: Parameter) -> Verify { return Verify(method: .p_updateAppRequired_set(newValue)) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func clear(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_clear, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CourseStructureManagerProtocol - -open class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getLoadedCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func shiftDueDates(courseID: String) throws { - addInvocation(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - do { - _ = try methodReturnValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - - fileprivate enum MethodType { - case m_getCourseBlocks__courseID_courseID(Parameter) - case m_getLoadedCourseBlocks__courseID_courseID(Parameter) - case m_shiftDueDates__courseID_courseID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseBlocks__courseID_courseID(let lhsCourseid), .m_getCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getLoadedCourseBlocks__courseID_courseID(let lhsCourseid), .m_getLoadedCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_shiftDueDates__courseID_courseID(let lhsCourseid), .m_shiftDueDates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_getLoadedCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_shiftDueDates__courseID_courseID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getCourseBlocks__courseID_courseID: return ".getCourseBlocks(courseID:)" - case .m_getLoadedCourseBlocks__courseID_courseID: return ".getLoadedCourseBlocks(courseID:)" - case .m_shiftDueDates__courseID_courseID: return ".shiftDueDates(courseID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getLoadedCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func shiftDueDates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func shiftDueDates(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseBlocks__courseID_courseID(`courseID`))} - public static func getLoadedCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`))} - public static func shiftDueDates(courseID: Parameter) -> Verify { return Verify(method: .m_shiftDueDates__courseID_courseID(`courseID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func getLoadedCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func shiftDueDates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_shiftDueDates__courseID_courseID(`courseID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DownloadManagerProtocol - -open class DownloadManagerProtocolMock: DownloadManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCurrentDownloadTask() -> DownloadDataTask? { - addInvocation(.m_getCurrentDownloadTask) - let perform = methodPerformValue(.m_getCurrentDownloadTask) as? () -> Void - perform?() - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_getCurrentDownloadTask).casted() - } catch { - // do nothing - } - return __value - } - - open func eventPublisher() -> AnyPublisher { - addInvocation(.m_eventPublisher) - let perform = methodPerformValue(.m_eventPublisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_eventPublisher).casted() - } catch { - onFatalFailure("Stub return value not specified for eventPublisher(). Use given") - Failure("Stub return value not specified for eventPublisher(). Use given") - } - return __value - } - - open func addToDownloadQueue(blocks: [CourseBlock]) throws { - addInvocation(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - do { - _ = try methodReturnValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getDownloadTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasks) - let perform = methodPerformValue(.m_getDownloadTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasks(). Use given") - Failure("Stub return value not specified for getDownloadTasks(). Use given") - } - return __value - } - - open func getDownloadTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func cancelDownloading(courseId: String, blocks: [CourseBlock]) throws { - addInvocation(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) as? (String, [CourseBlock]) -> Void - perform?(`courseId`, `blocks`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(task: DownloadDataTask) throws { - addInvocation(.m_cancelDownloading__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_cancelDownloading__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - do { - _ = try methodReturnValue(.m_cancelDownloading__task_task(Parameter.value(`task`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(courseId: String) throws { - addInvocation(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelAllDownloading() throws { - addInvocation(.m_cancelAllDownloading) - let perform = methodPerformValue(.m_cancelAllDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_cancelAllDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func deleteAll() { - addInvocation(.m_deleteAll) - let perform = methodPerformValue(.m_deleteAll) as? () -> Void - perform?() - } - - open func fileUrl(for blockId: String) -> URL? { - addInvocation(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: URL? = nil - do { - __value = try methodReturnValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func resumeDownloading() throws { - addInvocation(.m_resumeDownloading) - let perform = methodPerformValue(.m_resumeDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_resumeDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func isLargeVideosSize(blocks: [CourseBlock]) -> Bool { - addInvocation(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - Failure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - } - return __value - } - - open func removeAppSupportDirectoryUnusedContent() { - addInvocation(.m_removeAppSupportDirectoryUnusedContent) - let perform = methodPerformValue(.m_removeAppSupportDirectoryUnusedContent) as? () -> Void - perform?() - } - - open func delete(blocks: [CourseBlock], courseId: String) { - addInvocation(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) as? ([CourseBlock], String) -> Void - perform?(`blocks`, `courseId`) - } - - open func downloadTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getFreeDiskSpace() -> Int? { - addInvocation(.m_getFreeDiskSpace) - let perform = methodPerformValue(.m_getFreeDiskSpace) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getFreeDiskSpace).casted() - } catch { - // do nothing - } - return __value - } - - - fileprivate enum MethodType { - case m_getCurrentDownloadTask - case m_eventPublisher - case m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>) - case m_getDownloadTasks - case m_getDownloadTasksForCourse__courseId(Parameter) - case m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter, Parameter<[CourseBlock]>) - case m_cancelDownloading__task_task(Parameter) - case m_cancelDownloading__courseId_courseId(Parameter) - case m_cancelAllDownloading - case m_deleteAll - case m_fileUrl__for_blockId(Parameter) - case m_resumeDownloading - case m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>) - case m_removeAppSupportDirectoryUnusedContent - case m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>, Parameter) - case m_downloadTask__for_blockId(Parameter) - case m_getFreeDiskSpace - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCurrentDownloadTask, .m_getCurrentDownloadTask): return .match - - case (.m_eventPublisher, .m_eventPublisher): return .match - - case (.m_addToDownloadQueue__blocks_blocks(let lhsBlocks), .m_addToDownloadQueue__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadTasks, .m_getDownloadTasks): return .match - - case (.m_getDownloadTasksForCourse__courseId(let lhsCourseid), .m_getDownloadTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseIdblocks_blocks(let lhsCourseid, let lhsBlocks), .m_cancelDownloading__courseId_courseIdblocks_blocks(let rhsCourseid, let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__task_task(let lhsTask), .m_cancelDownloading__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseId(let lhsCourseid), .m_cancelDownloading__courseId_courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelAllDownloading, .m_cancelAllDownloading): return .match - - case (.m_deleteAll, .m_deleteAll): return .match - - case (.m_fileUrl__for_blockId(let lhsBlockid), .m_fileUrl__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_resumeDownloading, .m_resumeDownloading): return .match - - case (.m_isLargeVideosSize__blocks_blocks(let lhsBlocks), .m_isLargeVideosSize__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_removeAppSupportDirectoryUnusedContent, .m_removeAppSupportDirectoryUnusedContent): return .match - - case (.m_delete__blocks_blockscourseId_courseId(let lhsBlocks, let lhsCourseid), .m_delete__blocks_blockscourseId_courseId(let rhsBlocks, let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_downloadTask__for_blockId(let lhsBlockid), .m_downloadTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getFreeDiskSpace, .m_getFreeDiskSpace): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_getCurrentDownloadTask: return 0 - case .m_eventPublisher: return 0 - case let .m_addToDownloadQueue__blocks_blocks(p0): return p0.intValue - case .m_getDownloadTasks: return 0 - case let .m_getDownloadTasksForCourse__courseId(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseIdblocks_blocks(p0, p1): return p0.intValue + p1.intValue - case let .m_cancelDownloading__task_task(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseId(p0): return p0.intValue - case .m_cancelAllDownloading: return 0 - case .m_deleteAll: return 0 - case let .m_fileUrl__for_blockId(p0): return p0.intValue - case .m_resumeDownloading: return 0 - case let .m_isLargeVideosSize__blocks_blocks(p0): return p0.intValue - case .m_removeAppSupportDirectoryUnusedContent: return 0 - case let .m_delete__blocks_blockscourseId_courseId(p0, p1): return p0.intValue + p1.intValue - case let .m_downloadTask__for_blockId(p0): return p0.intValue - case .m_getFreeDiskSpace: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_getCurrentDownloadTask: return ".getCurrentDownloadTask()" - case .m_eventPublisher: return ".eventPublisher()" - case .m_addToDownloadQueue__blocks_blocks: return ".addToDownloadQueue(blocks:)" - case .m_getDownloadTasks: return ".getDownloadTasks()" - case .m_getDownloadTasksForCourse__courseId: return ".getDownloadTasksForCourse(_:)" - case .m_cancelDownloading__courseId_courseIdblocks_blocks: return ".cancelDownloading(courseId:blocks:)" - case .m_cancelDownloading__task_task: return ".cancelDownloading(task:)" - case .m_cancelDownloading__courseId_courseId: return ".cancelDownloading(courseId:)" - case .m_cancelAllDownloading: return ".cancelAllDownloading()" - case .m_deleteAll: return ".deleteAll()" - case .m_fileUrl__for_blockId: return ".fileUrl(for:)" - case .m_resumeDownloading: return ".resumeDownloading()" - case .m_isLargeVideosSize__blocks_blocks: return ".isLargeVideosSize(blocks:)" - case .m_removeAppSupportDirectoryUnusedContent: return ".removeAppSupportDirectoryUnusedContent()" - case .m_delete__blocks_blockscourseId_courseId: return ".delete(blocks:courseId:)" - case .m_downloadTask__for_blockId: return ".downloadTask(for:)" - case .m_getFreeDiskSpace: return ".getFreeDiskSpace()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCurrentDownloadTask(willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func eventPublisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func fileUrl(for blockId: Parameter, willReturn: URL?...) -> MethodStub { - return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getFreeDiskSpace(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCurrentDownloadTask(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func eventPublisher(willProduce: (Stubber>) -> Void) -> MethodStub { - let willReturn: [AnyPublisher] = [] - let given: Given = { return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - public static func getDownloadTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func fileUrl(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [URL?] = [] - let given: Given = { return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (URL?).self) - willProduce(stubber) - return given - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func downloadTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getFreeDiskSpace(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(task: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(task: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelAllDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelAllDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func resumeDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resumeDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCurrentDownloadTask() -> Verify { return Verify(method: .m_getCurrentDownloadTask)} - public static func eventPublisher() -> Verify { return Verify(method: .m_eventPublisher)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocks(`blocks`))} - public static func getDownloadTasks() -> Verify { return Verify(method: .m_getDownloadTasks)} - public static func getDownloadTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadTasksForCourse__courseId(`courseId`))} - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`))} - public static func cancelDownloading(task: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__task_task(`task`))} - public static func cancelDownloading(courseId: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseId(`courseId`))} - public static func cancelAllDownloading() -> Verify { return Verify(method: .m_cancelAllDownloading)} - public static func deleteAll() -> Verify { return Verify(method: .m_deleteAll)} - public static func fileUrl(for blockId: Parameter) -> Verify { return Verify(method: .m_fileUrl__for_blockId(`blockId`))} - public static func resumeDownloading() -> Verify { return Verify(method: .m_resumeDownloading)} - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_isLargeVideosSize__blocks_blocks(`blocks`))} - public static func removeAppSupportDirectoryUnusedContent() -> Verify { return Verify(method: .m_removeAppSupportDirectoryUnusedContent)} - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter) -> Verify { return Verify(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`))} - public static func downloadTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadTask__for_blockId(`blockId`))} - public static func getFreeDiskSpace() -> Verify { return Verify(method: .m_getFreeDiskSpace)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCurrentDownloadTask(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getCurrentDownloadTask, performs: perform) - } - public static func eventPublisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_eventPublisher, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), performs: perform) - } - public static func getDownloadTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadTasks, performs: perform) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, perform: @escaping (String, [CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), performs: perform) - } - public static func cancelDownloading(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__task_task(`task`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseId(`courseId`), performs: perform) - } - public static func cancelAllDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_cancelAllDownloading, performs: perform) - } - public static func deleteAll(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAll, performs: perform) - } - public static func fileUrl(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_fileUrl__for_blockId(`blockId`), performs: perform) - } - public static func resumeDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_resumeDownloading, performs: perform) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), performs: perform) - } - public static func removeAppSupportDirectoryUnusedContent(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeAppSupportDirectoryUnusedContent, performs: perform) - } - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter, perform: @escaping ([CourseBlock], String) -> Void) -> Perform { - return Perform(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`), performs: perform) - } - public static func downloadTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadTask__for_blockId(`blockId`), performs: perform) - } - public static func getFreeDiskSpace(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getFreeDiskSpace, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - OfflineSyncInteractorProtocol - -open class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func submitOfflineProgress(courseID: String, blockID: String, data: String) throws -> Bool { - addInvocation(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) - let perform = methodPerformValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) as? (String, String, String) -> Void - perform?(`courseID`, `blockID`, `data`) - var __value: Bool - do { - __value = try methodReturnValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - Failure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter, Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let lhsCourseid, let lhsBlockid, let lhsData), .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let rhsCourseid, let rhsBlockid, let rhsData)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsData, rhs: rhsData, with: matcher), lhsData, rhsData, "data")) - return Matcher.ComparisonResult(results) - } - } - - func intValue() -> Int { - switch self { - case let .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data: return ".submitOfflineProgress(courseID:blockID:data:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter) -> Verify { return Verify(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - diff --git a/Core/CoreTests/DownloadManager/DownloadManagerTests.swift b/Core/CoreTests/DownloadManager/DownloadManagerTests.swift index a88a69ca8..61f6f389b 100644 --- a/Core/CoreTests/DownloadManager/DownloadManagerTests.swift +++ b/Core/CoreTests/DownloadManager/DownloadManagerTests.swift @@ -6,171 +6,203 @@ // import XCTest -import SwiftyMocky +import Combine @testable import Core @MainActor final class DownloadManagerTests: XCTestCase { - + var persistence: CorePersistenceProtocolMock! var storage: CoreStorageMock! var connectivity: ConnectivityProtocolMock! - + override func setUp() { super.setUp() persistence = CorePersistenceProtocolMock() - let mockTask = createMockDownloadTask() storage = CoreStorageMock() connectivity = ConnectivityProtocolMock() - Given(persistence, .getDownloadDataTasks(willReturn: [mockTask])) - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) - Given(storage, .user(getter: .init(id: 19, username: "username", email: "email", name: "name"))) + + let mockTask = createMockDownloadTask() + persistence.getDownloadDataTasksHandler = { [mockTask] } + connectivity.isInternetAvaliable = true + connectivity.internetReachableSubject = .init(.reachable) + storage.user = .init(id: 19, username: "username", email: "email", name: "name") } - + // MARK: - Test Add to Queue - + func testAddToDownloadQueue_WhenWiFiOnlyAndOnWiFi_ShouldAddToQueue() async throws { // Given - Given(connectivity, .isMobileData(getter: false)) - + connectivity.isMobileData = false + storage.userSettings = UserSettings( + wifiOnly: true, + streamingQuality: .auto, + downloadQuality: .auto, + playbackSpeed: 1.0 + ) + + var capturedBlocks: [CourseBlock]? + var capturedQuality: DownloadQuality? + persistence.addToDownloadQueueBlocksHandler = { blocks, quality in + capturedBlocks = blocks + capturedQuality = quality + } + let downloadManager = DownloadManager( persistence: persistence, appStorage: storage, connectivity: connectivity ) - - Given(storage, .userSettings(getter: UserSettings( - wifiOnly: true, - streamingQuality: .auto, - downloadQuality: .auto, - playbackSpeed: 1.0 - ))) - + let blocks = [createMockCourseBlock()] - + // When try await downloadManager.addToDownloadQueue(blocks: blocks) + // Then - Verify(persistence, 1, .addToDownloadQueue(blocks: .value(blocks), downloadQuality: .value(.auto))) + XCTAssertEqual(persistence.addToDownloadQueueBlocksCallCount, 1) + XCTAssertEqual(capturedBlocks?.count, blocks.count) + XCTAssertEqual(capturedQuality, .auto) } - + func testAddToDownloadQueue_WhenWiFiOnlyAndOnMobileData_ShouldThrowError() async { // Given - Given(storage, .userSettings(getter: UserSettings( + storage.userSettings = UserSettings( wifiOnly: true, streamingQuality: .auto, downloadQuality: .auto, playbackSpeed: 1.0 - ))) - Given(connectivity, .isMobileData(getter: true)) - + ) + connectivity.isMobileData = true + let downloadManager = DownloadManager( persistence: persistence, appStorage: storage, connectivity: connectivity ) - + let blocks = [createMockCourseBlock()] - + // When/Then do { try await downloadManager.addToDownloadQueue(blocks: blocks) XCTFail("Should throw NoWiFiError") } catch is NoWiFiError { // Success - Verify(persistence, 0, .addToDownloadQueue(blocks: .any, downloadQuality: .value(.auto))) + XCTAssertEqual(persistence.addToDownloadQueueBlocksCallCount, 0) } catch { XCTFail("Unexpected error: \(error)") } } - + // MARK: - Test New Download - + func testNewDownload_WhenTaskAvailable_ShouldStartDownloading() async throws { // Given let mockTask = createMockDownloadTask() - Given(persistence, .getDownloadDataTasks(willReturn: [mockTask])) -// Given(persistence, .nextBlockForDownloading(willReturn: mockTask)) - Given(connectivity, .isMobileData(getter: false)) - + persistence.getDownloadDataTasksHandler = { [mockTask] } + connectivity.isMobileData = false + let downloadManager = DownloadManager( persistence: persistence, appStorage: storage, connectivity: connectivity ) - + // When try await downloadManager.resumeDownloading() let currentDownloadTask: DownloadDataTask? = Mirror(reflecting: downloadManager).descendant("currentDownloadTask") as? DownloadDataTask + // Then XCTAssertEqual(currentDownloadTask?.id, mockTask.id) } - + // MARK: - Test Cancel Downloads - + func testCancelDownloading_ForSpecificTask_ShouldRemoveFileAndTask() async throws { // Given let task = createMockDownloadTask() - Given(connectivity, .isMobileData(getter: false)) - + connectivity.isMobileData = false + + var deletedIds: [String]? + persistence.deleteDownloadDataTasksHandler = { ids in + deletedIds = ids + } + let downloadManager = DownloadManager( persistence: persistence, appStorage: storage, connectivity: connectivity ) - + // When try await downloadManager.cancelDownloading(task: task) - + // Then - Verify(persistence, 1, .deleteDownloadDataTasks(ids: .value([task.id]))) + XCTAssertEqual(persistence.deleteDownloadDataTasksCallCount, 1) + XCTAssertEqual(deletedIds, [task.id]) } - + func testCancelDownloading_ForCourse_ShouldCancelAllTasksForCourse() async throws { // Given let courseId = "course123" let task = createMockDownloadTask(courseId: courseId) let tasks = [task] - Given(connectivity, .isMobileData(getter: false)) - Given(persistence, .getDownloadDataTasksForCourse(.value(courseId), willReturn: tasks)) - + connectivity.isMobileData = false + + persistence.getDownloadDataTasksForCourseHandler = { requestedCourseId in + return requestedCourseId == courseId ? tasks : [] + } + + var deletedIds: [String]? + persistence.deleteDownloadDataTasksHandler = { ids in + deletedIds = ids + } + let downloadManager = DownloadManager( persistence: persistence, appStorage: storage, connectivity: connectivity ) - + // When try await downloadManager.cancelDownloading(courseId: courseId) - + // Then - Verify(persistence, 1, .getDownloadDataTasksForCourse(.value(courseId))) - Verify(persistence, 1, .deleteDownloadDataTasks(ids: .value([task.id]))) + XCTAssertEqual(persistence.getDownloadDataTasksForCourseCallCount, 1) + XCTAssertEqual(persistence.deleteDownloadDataTasksCallCount, 1) + XCTAssertEqual(deletedIds, [task.id]) } - + // MARK: - Test File Management - + func testDeleteFile_ShouldRemoveFileAndTask() async { // Given let block = createMockCourseBlock() let task = createMockDownloadTask() - Given(connectivity, .isMobileData(getter: false)) - Given(persistence, .getDownloadDataTasksForCourse(.value(block.courseId), willReturn: [task])) - + connectivity.isMobileData = false + + persistence.getDownloadDataTasksForCourseHandler = { _ in [task] } + + var deletedIds: [String]? + persistence.deleteDownloadDataTasksHandler = { ids in + deletedIds = ids + } + let downloadManager = DownloadManager( persistence: persistence, appStorage: storage, connectivity: connectivity ) - + // When await downloadManager.delete(blocks: [block], courseId: block.courseId) - + // Then - Verify(persistence, 1, .deleteDownloadDataTasks(ids: .value([task.id]))) + XCTAssertEqual(persistence.deleteDownloadDataTasksCallCount, 1) + XCTAssertEqual(deletedIds, [task.id]) } - + func testFileUrl_ForFinishedTask_ShouldReturnCorrectUrl() async { // Given let task = createMockDownloadTask(state: .finished) @@ -180,94 +212,97 @@ final class DownloadManagerTests: XCTestCase { email: "test@test.com", name: "Test User" ) - - Given(storage, .user(getter: mockUser)) - Given(connectivity, .isMobileData(getter: false)) - Given(persistence, .downloadDataTask(for: .value(task.id), willReturn: task)) - + + storage.user = mockUser + connectivity.isMobileData = false + + persistence.downloadDataTaskHandler = { blockId in + return blockId == task.id ? task : nil + } + let downloadManager = DownloadManager( persistence: persistence, appStorage: storage, connectivity: connectivity ) - + // When let url = await downloadManager.fileUrl(for: task.id) - + // Then XCTAssertNotNil(url) - Verify(persistence, 1, .downloadDataTask(for: .value(task.id))) + XCTAssertEqual(persistence.downloadDataTaskCallCount, 1) XCTAssertEqual(url?.lastPathComponent, task.fileName) } - + // MARK: - Test Video Size Calculation - + func testIsLargeVideosSize_WhenOver1GB_ShouldReturnTrue() async { // Given let blocks = [createMockCourseBlock(videoSize: 1_200_000_000)] // 1.2 GB - Given(connectivity, .isMobileData(getter: false)) - + connectivity.isMobileData = false + let downloadManager = DownloadManager( persistence: persistence, appStorage: storage, connectivity: connectivity ) - + // When let isLarge = await downloadManager.isLargeVideosSize(blocks: blocks) - + // Then XCTAssertTrue(isLarge) } - + func testIsLargeVideosSize_WhenUnder1GB_ShouldReturnFalse() async { // Given let blocks = [createMockCourseBlock(videoSize: 500_000_000)] // 500 MB - Given(connectivity, .isMobileData(getter: false)) - + connectivity.isMobileData = false + let downloadManager = DownloadManager( persistence: persistence, appStorage: storage, connectivity: connectivity ) - + // When let isLarge = await downloadManager.isLargeVideosSize(blocks: blocks) - + // Then XCTAssertFalse(isLarge) } - + // MARK: - Test Download Tasks Retrieval - + func testGetDownloadTasks_ShouldReturnAllTasks() async { // Given let expectedTasks = [ createMockDownloadTask(id: "1"), createMockDownloadTask(id: "2") ] - - Given(connectivity, .isMobileData(getter: false)) - Given(persistence, .getDownloadDataTasks(willReturn: expectedTasks)) - + + connectivity.isMobileData = false + persistence.getDownloadDataTasksHandler = { expectedTasks } + let downloadManager = DownloadManager( persistence: persistence, appStorage: storage, connectivity: connectivity ) - + // When let tasks = await downloadManager.getDownloadTasks() - + // Then - Verify(persistence, 1, .getDownloadDataTasks()) + XCTAssertEqual(persistence.getDownloadDataTasksCallCount, 1) XCTAssertEqual(tasks.count, expectedTasks.count) XCTAssertEqual(tasks[0].id, expectedTasks[0].id) XCTAssertEqual(tasks[1].id, expectedTasks[1].id) } - + // MARK: - Helper Methods - + private func createMockDownloadTask( id: String = "test123", courseId: String = "course123", @@ -290,7 +325,7 @@ final class DownloadManagerTests: XCTestCase { actualSize: 333 ) } - + private func createMockCourseBlock(videoSize: Int = 1000) -> CourseBlock { CourseBlock( blockId: "block123", diff --git a/Core/CoreTests/Generated/CoreMocks.generated.swift b/Core/CoreTests/Generated/CoreMocks.generated.swift new file mode 100644 index 000000000..45a37fe58 --- /dev/null +++ b/Core/CoreTests/Generated/CoreMocks.generated.swift @@ -0,0 +1,1804 @@ +/// +/// @Generated by Mockolo +/// + + + +import Alamofire +import Combine +@testable import Core +import CoreData +import Foundation +import OEXFoundation +import SwiftUI +import ZipArchive + + +public final class ConfigProtocolMock: ConfigProtocol, @unchecked Sendable { + public init() { } + public init(baseURL: URL = URL(fileURLWithPath: ""), baseSSOURL: URL = URL(fileURLWithPath: ""), ssoFinishedURL: URL = URL(fileURLWithPath: ""), ssoButtonTitle: [String: Any] = [String: Any](), oAuthClientId: String = "", tokenType: TokenType, feedbackEmail: String = "", appStoreLink: String = "", faq: URL? = nil, platformName: String = "", agreement: AgreementConfig, firebase: FirebaseConfig, facebook: FacebookConfig, microsoft: MicrosoftConfig, google: GoogleConfig, appleSignIn: AppleSignInConfig, features: FeaturesConfig, theme: ThemeConfig, uiComponents: UIComponentsConfig, discovery: DiscoveryConfig, dashboard: DashboardConfig, braze: BrazeConfig, branch: BranchConfig, program: DiscoveryConfig, experimentalFeatures: ExperimentalFeaturesConfig, URIScheme: String = "") { + self.baseURL = baseURL + self.baseSSOURL = baseSSOURL + self.ssoFinishedURL = ssoFinishedURL + self.ssoButtonTitle = ssoButtonTitle + self.oAuthClientId = oAuthClientId + self._tokenType = tokenType + self.feedbackEmail = feedbackEmail + self.appStoreLink = appStoreLink + self.faq = faq + self.platformName = platformName + self._agreement = agreement + self._firebase = firebase + self._facebook = facebook + self._microsoft = microsoft + self._google = google + self._appleSignIn = appleSignIn + self._features = features + self._theme = theme + self._uiComponents = uiComponents + self._discovery = discovery + self._dashboard = dashboard + self._braze = braze + self._branch = branch + self._program = program + self._experimentalFeatures = experimentalFeatures + self.URIScheme = URIScheme + } + + + + public var baseURL: URL = URL(fileURLWithPath: "") + + + public var baseSSOURL: URL = URL(fileURLWithPath: "") + + + public var ssoFinishedURL: URL = URL(fileURLWithPath: "") + + + public var ssoButtonTitle: [String: Any] = [String: Any]() + + + public var oAuthClientId: String = "" + + + private var _tokenType: TokenType! + public var tokenType: TokenType { + get { return _tokenType } + set { _tokenType = newValue } + } + + + public var feedbackEmail: String = "" + + + public var appStoreLink: String = "" + + + public var faq: URL? = nil + + + public var platformName: String = "" + + + private var _agreement: AgreementConfig! + public var agreement: AgreementConfig { + get { return _agreement } + set { _agreement = newValue } + } + + + private var _firebase: FirebaseConfig! + public var firebase: FirebaseConfig { + get { return _firebase } + set { _firebase = newValue } + } + + + private var _facebook: FacebookConfig! + public var facebook: FacebookConfig { + get { return _facebook } + set { _facebook = newValue } + } + + + private var _microsoft: MicrosoftConfig! + public var microsoft: MicrosoftConfig { + get { return _microsoft } + set { _microsoft = newValue } + } + + + private var _google: GoogleConfig! + public var google: GoogleConfig { + get { return _google } + set { _google = newValue } + } + + + private var _appleSignIn: AppleSignInConfig! + public var appleSignIn: AppleSignInConfig { + get { return _appleSignIn } + set { _appleSignIn = newValue } + } + + + private var _features: FeaturesConfig! + public var features: FeaturesConfig { + get { return _features } + set { _features = newValue } + } + + + private var _theme: ThemeConfig! + public var theme: ThemeConfig { + get { return _theme } + set { _theme = newValue } + } + + + private var _uiComponents: UIComponentsConfig! + public var uiComponents: UIComponentsConfig { + get { return _uiComponents } + set { _uiComponents = newValue } + } + + + private var _discovery: DiscoveryConfig! + public var discovery: DiscoveryConfig { + get { return _discovery } + set { _discovery = newValue } + } + + + private var _dashboard: DashboardConfig! + public var dashboard: DashboardConfig { + get { return _dashboard } + set { _dashboard = newValue } + } + + + private var _braze: BrazeConfig! + public var braze: BrazeConfig { + get { return _braze } + set { _braze = newValue } + } + + + private var _branch: BranchConfig! + public var branch: BranchConfig { + get { return _branch } + set { _branch = newValue } + } + + + private var _program: DiscoveryConfig! + public var program: DiscoveryConfig { + get { return _program } + set { _program = newValue } + } + + + private var _experimentalFeatures: ExperimentalFeaturesConfig! + public var experimentalFeatures: ExperimentalFeaturesConfig { + get { return _experimentalFeatures } + set { _experimentalFeatures = newValue } + } + + + public var URIScheme: String = "" +} + +public final class CoreAnalyticsMock: CoreAnalytics { + public init() { } + + + public private(set) var trackEventCallCount = 0 + public var trackEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackEventCallCount += 1 + if let trackEventHandler = trackEventHandler { + trackEventHandler(event, parameters) + } + + } + + public private(set) var trackEventBiValueCallCount = 0 + public var trackEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackEventBiValueCallCount += 1 + if let trackEventBiValueHandler = trackEventBiValueHandler { + trackEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var trackScreenEventCallCount = 0 + public var trackScreenEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackScreenEventCallCount += 1 + if let trackScreenEventHandler = trackScreenEventHandler { + trackScreenEventHandler(event, parameters) + } + + } + + public private(set) var trackScreenEventBiValueCallCount = 0 + public var trackScreenEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackScreenEventBiValueCallCount += 1 + if let trackScreenEventBiValueHandler = trackScreenEventBiValueHandler { + trackScreenEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var appreviewCallCount = 0 + public var appreviewHandler: ((AnalyticsEvent, EventBIValue, String?, Int?) -> ())? + public func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { + appreviewCallCount += 1 + if let appreviewHandler = appreviewHandler { + appreviewHandler(event, biValue, action, rating) + } + + } + + public private(set) var videoQualityChangedCallCount = 0 + public var videoQualityChangedHandler: ((AnalyticsEvent, EventBIValue, String, String) -> ())? + public func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { + videoQualityChangedCallCount += 1 + if let videoQualityChangedHandler = videoQualityChangedHandler { + videoQualityChangedHandler(event, bivalue, value, oldValue) + } + + } +} + +public final class CoreStorageMock: CoreStorage, @unchecked Sendable { + public init() { } + public init(accessToken: String? = nil, refreshToken: String? = nil, pushToken: String? = nil, appleSignFullName: String? = nil, appleSignEmail: String? = nil, cookiesDate: Date? = nil, reviewLastShownVersion: String? = nil, lastReviewDate: Date? = nil, user: DataLayer.User? = nil, userSettings: UserSettings? = nil, resetAppSupportDirectoryUserData: Bool? = nil, useRelativeDates: Bool = false, lastUsedSocialAuth: String? = nil, latestAvailableAppVersion: String? = nil, updateAppRequired: Bool = false) { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.pushToken = pushToken + self.appleSignFullName = appleSignFullName + self.appleSignEmail = appleSignEmail + self.cookiesDate = cookiesDate + self.reviewLastShownVersion = reviewLastShownVersion + self.lastReviewDate = lastReviewDate + self.user = user + self.userSettings = userSettings + self.resetAppSupportDirectoryUserData = resetAppSupportDirectoryUserData + self.useRelativeDates = useRelativeDates + self.lastUsedSocialAuth = lastUsedSocialAuth + self.latestAvailableAppVersion = latestAvailableAppVersion + self.updateAppRequired = updateAppRequired + } + + + public private(set) var accessTokenSetCallCount = 0 + public var accessToken: String? = nil { didSet { accessTokenSetCallCount += 1 } } + + public private(set) var refreshTokenSetCallCount = 0 + public var refreshToken: String? = nil { didSet { refreshTokenSetCallCount += 1 } } + + public private(set) var pushTokenSetCallCount = 0 + public var pushToken: String? = nil { didSet { pushTokenSetCallCount += 1 } } + + public private(set) var appleSignFullNameSetCallCount = 0 + public var appleSignFullName: String? = nil { didSet { appleSignFullNameSetCallCount += 1 } } + + public private(set) var appleSignEmailSetCallCount = 0 + public var appleSignEmail: String? = nil { didSet { appleSignEmailSetCallCount += 1 } } + + public private(set) var cookiesDateSetCallCount = 0 + public var cookiesDate: Date? = nil { didSet { cookiesDateSetCallCount += 1 } } + + public private(set) var reviewLastShownVersionSetCallCount = 0 + public var reviewLastShownVersion: String? = nil { didSet { reviewLastShownVersionSetCallCount += 1 } } + + public private(set) var lastReviewDateSetCallCount = 0 + public var lastReviewDate: Date? = nil { didSet { lastReviewDateSetCallCount += 1 } } + + public private(set) var userSetCallCount = 0 + public var user: DataLayer.User? = nil { didSet { userSetCallCount += 1 } } + + public private(set) var userSettingsSetCallCount = 0 + public var userSettings: UserSettings? = nil { didSet { userSettingsSetCallCount += 1 } } + + public private(set) var resetAppSupportDirectoryUserDataSetCallCount = 0 + public var resetAppSupportDirectoryUserData: Bool? = nil { didSet { resetAppSupportDirectoryUserDataSetCallCount += 1 } } + + public private(set) var useRelativeDatesSetCallCount = 0 + public var useRelativeDates: Bool = false { didSet { useRelativeDatesSetCallCount += 1 } } + + public private(set) var lastUsedSocialAuthSetCallCount = 0 + public var lastUsedSocialAuth: String? = nil { didSet { lastUsedSocialAuthSetCallCount += 1 } } + + public private(set) var latestAvailableAppVersionSetCallCount = 0 + public var latestAvailableAppVersion: String? = nil { didSet { latestAvailableAppVersionSetCallCount += 1 } } + + public private(set) var updateAppRequiredSetCallCount = 0 + public var updateAppRequired: Bool = false { didSet { updateAppRequiredSetCallCount += 1 } } + + private let clearState = MockoloMutex(MockoloHandlerState ()>()) + public var clearCallCount: Int { + return clearState.withLock(\.callCount) + } + public var clearHandler: (@Sendable () -> ())? { + get { clearState.withLock(\.handler) } + set { clearState.withLock { $0.handler = newValue } } + } + public func clear() { + let clearHandler = clearState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearHandler = clearHandler { + clearHandler() + } + + } +} + +public final class AuthInteractorProtocolMock: AuthInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let loginState = MockoloMutex(MockoloHandlerState User>()) + public var loginCallCount: Int { + return loginState.withLock(\.callCount) + } + public var loginHandler: (@Sendable (String, String) async throws -> User)? { + get { loginState.withLock(\.handler) } + set { loginState.withLock { $0.handler = newValue } } + } + public func login(username: String, password: String) async throws -> User { + let loginHandler = loginState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginHandler = loginHandler { + return try await loginHandler(username, password) + } + fatalError("loginHandler returns can't have a default value thus its handler must be set") + } + + private let loginExternalTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginExternalTokenCallCount: Int { + return loginExternalTokenState.withLock(\.callCount) + } + public var loginExternalTokenHandler: (@Sendable (String, String) async throws -> User)? { + get { loginExternalTokenState.withLock(\.handler) } + set { loginExternalTokenState.withLock { $0.handler = newValue } } + } + public func login(externalToken: String, backend: String) async throws -> User { + let loginExternalTokenHandler = loginExternalTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginExternalTokenHandler = loginExternalTokenHandler { + return try await loginExternalTokenHandler(externalToken, backend) + } + fatalError("loginExternalTokenHandler returns can't have a default value thus its handler must be set") + } + + private let loginSsoTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginSsoTokenCallCount: Int { + return loginSsoTokenState.withLock(\.callCount) + } + public var loginSsoTokenHandler: (@Sendable (String) async throws -> User)? { + get { loginSsoTokenState.withLock(\.handler) } + set { loginSsoTokenState.withLock { $0.handler = newValue } } + } + public func login(ssoToken: String) async throws -> User { + let loginSsoTokenHandler = loginSsoTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginSsoTokenHandler = loginSsoTokenHandler { + return try await loginSsoTokenHandler(ssoToken) + } + fatalError("loginSsoTokenHandler returns can't have a default value thus its handler must be set") + } + + private let resetPasswordState = MockoloMutex(MockoloHandlerState ResetPassword>()) + public var resetPasswordCallCount: Int { + return resetPasswordState.withLock(\.callCount) + } + public var resetPasswordHandler: (@Sendable (String) async throws -> ResetPassword)? { + get { resetPasswordState.withLock(\.handler) } + set { resetPasswordState.withLock { $0.handler = newValue } } + } + public func resetPassword(email: String) async throws -> ResetPassword { + let resetPasswordHandler = resetPasswordState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resetPasswordHandler = resetPasswordHandler { + return try await resetPasswordHandler(email) + } + fatalError("resetPasswordHandler returns can't have a default value thus its handler must be set") + } + + private let getCookiesState = MockoloMutex(MockoloHandlerState ()>()) + public var getCookiesCallCount: Int { + return getCookiesState.withLock(\.callCount) + } + public var getCookiesHandler: (@Sendable (Bool) async throws -> ())? { + get { getCookiesState.withLock(\.handler) } + set { getCookiesState.withLock { $0.handler = newValue } } + } + public func getCookies(force: Bool) async throws { + let getCookiesHandler = getCookiesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCookiesHandler = getCookiesHandler { + try await getCookiesHandler(force) + } + + } + + private let getRegistrationFieldsState = MockoloMutex(MockoloHandlerState [PickerFields]>()) + public var getRegistrationFieldsCallCount: Int { + return getRegistrationFieldsState.withLock(\.callCount) + } + public var getRegistrationFieldsHandler: (@Sendable () async throws -> [PickerFields])? { + get { getRegistrationFieldsState.withLock(\.handler) } + set { getRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func getRegistrationFields() async throws -> [PickerFields] { + let getRegistrationFieldsHandler = getRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getRegistrationFieldsHandler = getRegistrationFieldsHandler { + return try await getRegistrationFieldsHandler() + } + return [PickerFields]() + } + + private let registerUserState = MockoloMutex(MockoloHandlerState User>()) + public var registerUserCallCount: Int { + return registerUserState.withLock(\.callCount) + } + public var registerUserHandler: (@Sendable ([String: String], Bool) async throws -> User)? { + get { registerUserState.withLock(\.handler) } + set { registerUserState.withLock { $0.handler = newValue } } + } + public func registerUser(fields: [String: String], isSocial: Bool) async throws -> User { + let registerUserHandler = registerUserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let registerUserHandler = registerUserHandler { + return try await registerUserHandler(fields, isSocial) + } + fatalError("registerUserHandler returns can't have a default value thus its handler must be set") + } + + private let validateRegistrationFieldsState = MockoloMutex(MockoloHandlerState [String: String]>()) + public var validateRegistrationFieldsCallCount: Int { + return validateRegistrationFieldsState.withLock(\.callCount) + } + public var validateRegistrationFieldsHandler: (@Sendable ([String: String]) async throws -> [String: String])? { + get { validateRegistrationFieldsState.withLock(\.handler) } + set { validateRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func validateRegistrationFields(fields: [String: String]) async throws -> [String: String] { + let validateRegistrationFieldsHandler = validateRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let validateRegistrationFieldsHandler = validateRegistrationFieldsHandler { + return try await validateRegistrationFieldsHandler(fields) + } + return [String: String]() + } +} + +public final class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let submitOfflineProgressState = MockoloMutex(MockoloHandlerState Bool>()) + public var submitOfflineProgressCallCount: Int { + return submitOfflineProgressState.withLock(\.callCount) + } + public var submitOfflineProgressHandler: (@Sendable (String, String, String) async throws -> Bool)? { + get { submitOfflineProgressState.withLock(\.handler) } + set { submitOfflineProgressState.withLock { $0.handler = newValue } } + } + public func submitOfflineProgress(courseID: String, blockID: String, data: String) async throws -> Bool { + let submitOfflineProgressHandler = submitOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let submitOfflineProgressHandler = submitOfflineProgressHandler { + return try await submitOfflineProgressHandler(courseID, blockID, data) + } + return false + } +} + +public final class WebviewCookiesUpdateProtocolMock: WebviewCookiesUpdateProtocol { + public init() { } + public init(authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock(), cookiesReady: Bool = false, updatingCookies: Bool = false, errorMessage: String? = nil) { + self.authInteractor = authInteractor + self.cookiesReady = cookiesReady + self.updatingCookies = updatingCookies + self.errorMessage = errorMessage + } + + + + public var authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock() + + public private(set) var cookiesReadySetCallCount = 0 + public var cookiesReady: Bool = false { didSet { cookiesReadySetCallCount += 1 } } + + public private(set) var updatingCookiesSetCallCount = 0 + public var updatingCookies: Bool = false { didSet { updatingCookiesSetCallCount += 1 } } + + public private(set) var errorMessageSetCallCount = 0 + public var errorMessage: String? = nil { didSet { errorMessageSetCallCount += 1 } } + + public private(set) var updateCookiesCallCount = 0 + public var updateCookiesHandler: ((Bool, Int) async -> ())? + public func updateCookies(force: Bool, retryCount: Int) async { + updateCookiesCallCount += 1 + if let updateCookiesHandler = updateCookiesHandler { + await updateCookiesHandler(force, retryCount) + } + + } +} + +public final class BaseRouterMock: BaseRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class CalendarManagerProtocolMock: CalendarManagerProtocol, @unchecked Sendable { + public init() { } + + + private let createCalendarIfNeededState = MockoloMutex(MockoloHandlerState ()>()) + public var createCalendarIfNeededCallCount: Int { + return createCalendarIfNeededState.withLock(\.callCount) + } + public var createCalendarIfNeededHandler: (@Sendable () -> ())? { + get { createCalendarIfNeededState.withLock(\.handler) } + set { createCalendarIfNeededState.withLock { $0.handler = newValue } } + } + public func createCalendarIfNeeded() { + let createCalendarIfNeededHandler = createCalendarIfNeededState.withLock { state in + state.callCount += 1 + return state.handler + } + if let createCalendarIfNeededHandler = createCalendarIfNeededHandler { + createCalendarIfNeededHandler() + } + + } + + private let filterCoursesBySelectedState = MockoloMutex(MockoloHandlerState [CourseForSync]>()) + public var filterCoursesBySelectedCallCount: Int { + return filterCoursesBySelectedState.withLock(\.callCount) + } + public var filterCoursesBySelectedHandler: (@Sendable ([CourseForSync]) async -> [CourseForSync])? { + get { filterCoursesBySelectedState.withLock(\.handler) } + set { filterCoursesBySelectedState.withLock { $0.handler = newValue } } + } + public func filterCoursesBySelected(fetchedCourses: [CourseForSync]) async -> [CourseForSync] { + let filterCoursesBySelectedHandler = filterCoursesBySelectedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let filterCoursesBySelectedHandler = filterCoursesBySelectedHandler { + return await filterCoursesBySelectedHandler(fetchedCourses) + } + return [CourseForSync]() + } + + private let removeOldCalendarState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOldCalendarCallCount: Int { + return removeOldCalendarState.withLock(\.callCount) + } + public var removeOldCalendarHandler: (@Sendable () -> ())? { + get { removeOldCalendarState.withLock(\.handler) } + set { removeOldCalendarState.withLock { $0.handler = newValue } } + } + public func removeOldCalendar() { + let removeOldCalendarHandler = removeOldCalendarState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOldCalendarHandler = removeOldCalendarHandler { + removeOldCalendarHandler() + } + + } + + private let removeOutdatedEventsState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOutdatedEventsCallCount: Int { + return removeOutdatedEventsState.withLock(\.callCount) + } + public var removeOutdatedEventsHandler: (@Sendable (String) async -> ())? { + get { removeOutdatedEventsState.withLock(\.handler) } + set { removeOutdatedEventsState.withLock { $0.handler = newValue } } + } + public func removeOutdatedEvents(courseID: String) async { + let removeOutdatedEventsHandler = removeOutdatedEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOutdatedEventsHandler = removeOutdatedEventsHandler { + await removeOutdatedEventsHandler(courseID) + } + + } + + private let syncCourseState = MockoloMutex(MockoloHandlerState ()>()) + public var syncCourseCallCount: Int { + return syncCourseState.withLock(\.callCount) + } + public var syncCourseHandler: (@Sendable (String, String, CourseDates) async -> ())? { + get { syncCourseState.withLock(\.handler) } + set { syncCourseState.withLock { $0.handler = newValue } } + } + public func syncCourse(courseID: String, courseName: String, dates: CourseDates) async { + let syncCourseHandler = syncCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let syncCourseHandler = syncCourseHandler { + await syncCourseHandler(courseID, courseName, dates) + } + + } + + private let requestAccessState = MockoloMutex(MockoloHandlerState Bool>()) + public var requestAccessCallCount: Int { + return requestAccessState.withLock(\.callCount) + } + public var requestAccessHandler: (@Sendable () async -> Bool)? { + get { requestAccessState.withLock(\.handler) } + set { requestAccessState.withLock { $0.handler = newValue } } + } + public func requestAccess() async -> Bool { + let requestAccessHandler = requestAccessState.withLock { state in + state.callCount += 1 + return state.handler + } + if let requestAccessHandler = requestAccessHandler { + return await requestAccessHandler() + } + return false + } + + private let courseStatusState = MockoloMutex(MockoloHandlerState SyncStatus>()) + public var courseStatusCallCount: Int { + return courseStatusState.withLock(\.callCount) + } + public var courseStatusHandler: (@Sendable (String) async -> SyncStatus)? { + get { courseStatusState.withLock(\.handler) } + set { courseStatusState.withLock { $0.handler = newValue } } + } + public func courseStatus(courseID: String) async -> SyncStatus { + let courseStatusHandler = courseStatusState.withLock { state in + state.callCount += 1 + return state.handler + } + if let courseStatusHandler = courseStatusHandler { + return await courseStatusHandler(courseID) + } + fatalError("courseStatusHandler returns can't have a default value thus its handler must be set") + } + + private let clearAllDataState = MockoloMutex(MockoloHandlerState ()>()) + public var clearAllDataCallCount: Int { + return clearAllDataState.withLock(\.callCount) + } + public var clearAllDataHandler: (@Sendable (Bool) async -> ())? { + get { clearAllDataState.withLock(\.handler) } + set { clearAllDataState.withLock { $0.handler = newValue } } + } + public func clearAllData(removeCalendar: Bool) async { + let clearAllDataHandler = clearAllDataState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearAllDataHandler = clearAllDataHandler { + await clearAllDataHandler(removeCalendar) + } + + } + + private let isDatesChangedState = MockoloMutex(MockoloHandlerState Bool>()) + public var isDatesChangedCallCount: Int { + return isDatesChangedState.withLock(\.callCount) + } + public var isDatesChangedHandler: (@Sendable (String, String) async -> Bool)? { + get { isDatesChangedState.withLock(\.handler) } + set { isDatesChangedState.withLock { $0.handler = newValue } } + } + public func isDatesChanged(courseID: String, checksum: String) async -> Bool { + let isDatesChangedHandler = isDatesChangedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isDatesChangedHandler = isDatesChangedHandler { + return await isDatesChangedHandler(courseID, checksum) + } + return false + } +} + +public final class CorePersistenceProtocolMock: CorePersistenceProtocol, @unchecked Sendable { + public init() { } + + + private let setState = MockoloMutex(MockoloHandlerState ()>()) + public var setCallCount: Int { + return setState.withLock(\.callCount) + } + public var setHandler: (@Sendable (Int) -> ())? { + get { setState.withLock(\.handler) } + set { setState.withLock { $0.handler = newValue } } + } + public func set(userId: Int) { + let setHandler = setState.withLock { state in + state.callCount += 1 + return state.handler + } + if let setHandler = setHandler { + setHandler(userId) + } + + } + + private let getUserIDState = MockoloMutex(MockoloHandlerState Int?>()) + public var getUserIDCallCount: Int { + return getUserIDState.withLock(\.callCount) + } + public var getUserIDHandler: (@Sendable () -> Int?)? { + get { getUserIDState.withLock(\.handler) } + set { getUserIDState.withLock { $0.handler = newValue } } + } + public func getUserID() -> Int? { + let getUserIDHandler = getUserIDState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getUserIDHandler = getUserIDHandler { + return getUserIDHandler() + } + return nil + } + + private let publisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var publisherCallCount: Int { + return publisherState.withLock(\.callCount) + } + public var publisherHandler: (@Sendable () throws -> AnyPublisher)? { + get { publisherState.withLock(\.handler) } + set { publisherState.withLock { $0.handler = newValue } } + } + public func publisher() throws -> AnyPublisher { + let publisherHandler = publisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let publisherHandler = publisherHandler { + return try publisherHandler() + } + fatalError("publisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([DownloadDataTask]) -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(tasks: [DownloadDataTask]) { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + addToDownloadQueueHandler(tasks) + } + + } + + private let saveOfflineProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var saveOfflineProgressCallCount: Int { + return saveOfflineProgressState.withLock(\.callCount) + } + public var saveOfflineProgressHandler: (@Sendable (OfflineProgress) async -> ())? { + get { saveOfflineProgressState.withLock(\.handler) } + set { saveOfflineProgressState.withLock { $0.handler = newValue } } + } + public func saveOfflineProgress(progress: OfflineProgress) async { + let saveOfflineProgressHandler = saveOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveOfflineProgressHandler = saveOfflineProgressHandler { + await saveOfflineProgressHandler(progress) + } + + } + + private let loadProgressState = MockoloMutex(MockoloHandlerState OfflineProgress?>()) + public var loadProgressCallCount: Int { + return loadProgressState.withLock(\.callCount) + } + public var loadProgressHandler: (@Sendable (String) async -> OfflineProgress?)? { + get { loadProgressState.withLock(\.handler) } + set { loadProgressState.withLock { $0.handler = newValue } } + } + public func loadProgress(for blockID: String) async -> OfflineProgress? { + let loadProgressHandler = loadProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadProgressHandler = loadProgressHandler { + return await loadProgressHandler(blockID) + } + return nil + } + + private let loadAllOfflineProgressState = MockoloMutex(MockoloHandlerState [OfflineProgress]>()) + public var loadAllOfflineProgressCallCount: Int { + return loadAllOfflineProgressState.withLock(\.callCount) + } + public var loadAllOfflineProgressHandler: (@Sendable () async -> [OfflineProgress])? { + get { loadAllOfflineProgressState.withLock(\.handler) } + set { loadAllOfflineProgressState.withLock { $0.handler = newValue } } + } + public func loadAllOfflineProgress() async -> [OfflineProgress] { + let loadAllOfflineProgressHandler = loadAllOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadAllOfflineProgressHandler = loadAllOfflineProgressHandler { + return await loadAllOfflineProgressHandler() + } + return [OfflineProgress]() + } + + private let deleteProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteProgressCallCount: Int { + return deleteProgressState.withLock(\.callCount) + } + public var deleteProgressHandler: (@Sendable (String) async -> ())? { + get { deleteProgressState.withLock(\.handler) } + set { deleteProgressState.withLock { $0.handler = newValue } } + } + public func deleteProgress(for blockID: String) async { + let deleteProgressHandler = deleteProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteProgressHandler = deleteProgressHandler { + await deleteProgressHandler(blockID) + } + + } + + private let deleteAllProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllProgressCallCount: Int { + return deleteAllProgressState.withLock(\.callCount) + } + public var deleteAllProgressHandler: (@Sendable () async -> ())? { + get { deleteAllProgressState.withLock(\.handler) } + set { deleteAllProgressState.withLock { $0.handler = newValue } } + } + public func deleteAllProgress() async { + let deleteAllProgressHandler = deleteAllProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllProgressHandler = deleteAllProgressHandler { + await deleteAllProgressHandler() + } + + } + + private let addToDownloadQueueBlocksState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueBlocksCallCount: Int { + return addToDownloadQueueBlocksState.withLock(\.callCount) + } + public var addToDownloadQueueBlocksHandler: (@Sendable ([CourseBlock], DownloadQuality) -> ())? { + get { addToDownloadQueueBlocksState.withLock(\.handler) } + set { addToDownloadQueueBlocksState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { + let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksHandler { + addToDownloadQueueBlocksHandler(blocks, downloadQuality) + } + + } + + private let updateTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var updateTaskCallCount: Int { + return updateTaskState.withLock(\.callCount) + } + public var updateTaskHandler: (@Sendable (DownloadDataTask) -> ())? { + get { updateTaskState.withLock(\.handler) } + set { updateTaskState.withLock { $0.handler = newValue } } + } + public func updateTask(task: DownloadDataTask) { + let updateTaskHandler = updateTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateTaskHandler = updateTaskHandler { + updateTaskHandler(task) + } + + } + + private let downloadDataTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadDataTaskCallCount: Int { + return downloadDataTaskState.withLock(\.callCount) + } + public var downloadDataTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadDataTaskState.withLock(\.handler) } + set { downloadDataTaskState.withLock { $0.handler = newValue } } + } + public func downloadDataTask(for blockId: String) async -> DownloadDataTask? { + let downloadDataTaskHandler = downloadDataTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadDataTaskHandler = downloadDataTaskHandler { + return await downloadDataTaskHandler(blockId) + } + return nil + } + + private let getDownloadDataTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksCallCount: Int { + return getDownloadDataTasksState.withLock(\.callCount) + } + public var getDownloadDataTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadDataTasksState.withLock(\.handler) } + set { getDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasks() async -> [DownloadDataTask] { + let getDownloadDataTasksHandler = getDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksHandler = getDownloadDataTasksHandler { + return await getDownloadDataTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadDataTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksForCourseCallCount: Int { + return getDownloadDataTasksForCourseState.withLock(\.callCount) + } + public var getDownloadDataTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadDataTasksForCourseState.withLock(\.handler) } + set { getDownloadDataTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseHandler { + return await getDownloadDataTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let deleteDownloadDataTasksState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteDownloadDataTasksCallCount: Int { + return deleteDownloadDataTasksState.withLock(\.callCount) + } + public var deleteDownloadDataTasksHandler: (@Sendable ([String]) -> ())? { + get { deleteDownloadDataTasksState.withLock(\.handler) } + set { deleteDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func deleteDownloadDataTasks(ids: [String]) { + let deleteDownloadDataTasksHandler = deleteDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteDownloadDataTasksHandler = deleteDownloadDataTasksHandler { + deleteDownloadDataTasksHandler(ids) + } + + } +} + +public final class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseBlocksCallCount: Int { + return getCourseBlocksState.withLock(\.callCount) + } + public var getCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getCourseBlocksState.withLock(\.handler) } + set { getCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseBlocks(courseID: String) async throws -> CourseStructure { + let getCourseBlocksHandler = getCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseBlocksHandler = getCourseBlocksHandler { + return try await getCourseBlocksHandler(courseID) + } + fatalError("getCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getLoadedCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getLoadedCourseBlocksCallCount: Int { + return getLoadedCourseBlocksState.withLock(\.callCount) + } + public var getLoadedCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getLoadedCourseBlocksState.withLock(\.handler) } + set { getLoadedCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure { + let getLoadedCourseBlocksHandler = getLoadedCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseBlocksHandler = getLoadedCourseBlocksHandler { + return try await getLoadedCourseBlocksHandler(courseID) + } + fatalError("getLoadedCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let shiftDueDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var shiftDueDatesCallCount: Int { + return shiftDueDatesState.withLock(\.callCount) + } + public var shiftDueDatesHandler: (@Sendable (String) async throws -> ())? { + get { shiftDueDatesState.withLock(\.handler) } + set { shiftDueDatesState.withLock { $0.handler = newValue } } + } + public func shiftDueDates(courseID: String) async throws { + let shiftDueDatesHandler = shiftDueDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let shiftDueDatesHandler = shiftDueDatesHandler { + try await shiftDueDatesHandler(courseID) + } + + } +} + +public final class ConnectivityProtocolMock: ConnectivityProtocol, @unchecked Sendable { + public init() { } + public init(isInternetAvaliable: Bool = false, isMobileData: Bool = false) { + self.isInternetAvaliable = isInternetAvaliable + self.isMobileData = isMobileData + } + + + + public var isInternetAvaliable: Bool = false + + + public var isMobileData: Bool = false + + + private var _internetReachableSubject: CurrentValueSubject! + public var internetReachableSubject: CurrentValueSubject { + get { return _internetReachableSubject } + set { _internetReachableSubject = newValue } + } +} + +public final class DownloadManagerProtocolMock: DownloadManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCurrentDownloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var getCurrentDownloadTaskCallCount: Int { + return getCurrentDownloadTaskState.withLock(\.callCount) + } + public var getCurrentDownloadTaskHandler: (@Sendable () async -> DownloadDataTask?)? { + get { getCurrentDownloadTaskState.withLock(\.handler) } + set { getCurrentDownloadTaskState.withLock { $0.handler = newValue } } + } + public func getCurrentDownloadTask() async -> DownloadDataTask? { + let getCurrentDownloadTaskHandler = getCurrentDownloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCurrentDownloadTaskHandler = getCurrentDownloadTaskHandler { + return await getCurrentDownloadTaskHandler() + } + return nil + } + + private let eventPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var eventPublisherCallCount: Int { + return eventPublisherState.withLock(\.callCount) + } + public var eventPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { eventPublisherState.withLock(\.handler) } + set { eventPublisherState.withLock { $0.handler = newValue } } + } + public func eventPublisher() -> AnyPublisher { + let eventPublisherHandler = eventPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let eventPublisherHandler = eventPublisherHandler { + return eventPublisherHandler() + } + fatalError("eventPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([CourseBlock]) async throws -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock]) async throws { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + try await addToDownloadQueueHandler(blocks) + } + + } + + private let getDownloadTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksCallCount: Int { + return getDownloadTasksState.withLock(\.callCount) + } + public var getDownloadTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadTasksState.withLock(\.handler) } + set { getDownloadTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadTasks() async -> [DownloadDataTask] { + let getDownloadTasksHandler = getDownloadTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksHandler = getDownloadTasksHandler { + return await getDownloadTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksForCourseCallCount: Int { + return getDownloadTasksForCourseState.withLock(\.callCount) + } + public var getDownloadTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadTasksForCourseState.withLock(\.handler) } + set { getDownloadTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadTasksForCourseHandler = getDownloadTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksForCourseHandler = getDownloadTasksForCourseHandler { + return await getDownloadTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let cancelDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCallCount: Int { + return cancelDownloadingState.withLock(\.callCount) + } + public var cancelDownloadingHandler: (@Sendable (String, [CourseBlock]) async throws -> ())? { + get { cancelDownloadingState.withLock(\.handler) } + set { cancelDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String, blocks: [CourseBlock]) async throws { + let cancelDownloadingHandler = cancelDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingHandler = cancelDownloadingHandler { + try await cancelDownloadingHandler(courseId, blocks) + } + + } + + private let cancelDownloadingTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingTaskCallCount: Int { + return cancelDownloadingTaskState.withLock(\.callCount) + } + public var cancelDownloadingTaskHandler: (@Sendable (DownloadDataTask) async throws -> ())? { + get { cancelDownloadingTaskState.withLock(\.handler) } + set { cancelDownloadingTaskState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(task: DownloadDataTask) async throws { + let cancelDownloadingTaskHandler = cancelDownloadingTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingTaskHandler = cancelDownloadingTaskHandler { + try await cancelDownloadingTaskHandler(task) + } + + } + + private let cancelDownloadingCourseIdState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCourseIdCallCount: Int { + return cancelDownloadingCourseIdState.withLock(\.callCount) + } + public var cancelDownloadingCourseIdHandler: (@Sendable (String) async throws -> ())? { + get { cancelDownloadingCourseIdState.withLock(\.handler) } + set { cancelDownloadingCourseIdState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String) async throws { + let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdHandler { + try await cancelDownloadingCourseIdHandler(courseId) + } + + } + + private let cancelAllDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelAllDownloadingCallCount: Int { + return cancelAllDownloadingState.withLock(\.callCount) + } + public var cancelAllDownloadingHandler: (@Sendable () async throws -> ())? { + get { cancelAllDownloadingState.withLock(\.handler) } + set { cancelAllDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelAllDownloading() async throws { + let cancelAllDownloadingHandler = cancelAllDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelAllDownloadingHandler = cancelAllDownloadingHandler { + try await cancelAllDownloadingHandler() + } + + } + + private let deleteAllState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllCallCount: Int { + return deleteAllState.withLock(\.callCount) + } + public var deleteAllHandler: (@Sendable () async -> ())? { + get { deleteAllState.withLock(\.handler) } + set { deleteAllState.withLock { $0.handler = newValue } } + } + public func deleteAll() async { + let deleteAllHandler = deleteAllState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllHandler = deleteAllHandler { + await deleteAllHandler() + } + + } + + private let fileUrlState = MockoloMutex(MockoloHandlerState URL?>()) + public var fileUrlCallCount: Int { + return fileUrlState.withLock(\.callCount) + } + public var fileUrlHandler: (@Sendable (String) async -> URL?)? { + get { fileUrlState.withLock(\.handler) } + set { fileUrlState.withLock { $0.handler = newValue } } + } + public func fileUrl(for blockId: String) async -> URL? { + let fileUrlHandler = fileUrlState.withLock { state in + state.callCount += 1 + return state.handler + } + if let fileUrlHandler = fileUrlHandler { + return await fileUrlHandler(blockId) + } + return nil + } + + private let resumeDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var resumeDownloadingCallCount: Int { + return resumeDownloadingState.withLock(\.callCount) + } + public var resumeDownloadingHandler: (@Sendable () async throws -> ())? { + get { resumeDownloadingState.withLock(\.handler) } + set { resumeDownloadingState.withLock { $0.handler = newValue } } + } + public func resumeDownloading() async throws { + let resumeDownloadingHandler = resumeDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resumeDownloadingHandler = resumeDownloadingHandler { + try await resumeDownloadingHandler() + } + + } + + private let isLargeVideosSizeState = MockoloMutex(MockoloHandlerState Bool>()) + public var isLargeVideosSizeCallCount: Int { + return isLargeVideosSizeState.withLock(\.callCount) + } + public var isLargeVideosSizeHandler: (@Sendable ([CourseBlock]) async -> Bool)? { + get { isLargeVideosSizeState.withLock(\.handler) } + set { isLargeVideosSizeState.withLock { $0.handler = newValue } } + } + public func isLargeVideosSize(blocks: [CourseBlock]) async -> Bool { + let isLargeVideosSizeHandler = isLargeVideosSizeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isLargeVideosSizeHandler = isLargeVideosSizeHandler { + return await isLargeVideosSizeHandler(blocks) + } + return false + } + + private let removeAppSupportDirectoryUnusedContentState = MockoloMutex(MockoloHandlerState ()>()) + public var removeAppSupportDirectoryUnusedContentCallCount: Int { + return removeAppSupportDirectoryUnusedContentState.withLock(\.callCount) + } + public var removeAppSupportDirectoryUnusedContentHandler: (@Sendable () -> ())? { + get { removeAppSupportDirectoryUnusedContentState.withLock(\.handler) } + set { removeAppSupportDirectoryUnusedContentState.withLock { $0.handler = newValue } } + } + public func removeAppSupportDirectoryUnusedContent() { + let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentHandler { + removeAppSupportDirectoryUnusedContentHandler() + } + + } + + private let deleteState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteCallCount: Int { + return deleteState.withLock(\.callCount) + } + public var deleteHandler: (@Sendable ([CourseBlock], String) async -> ())? { + get { deleteState.withLock(\.handler) } + set { deleteState.withLock { $0.handler = newValue } } + } + public func delete(blocks: [CourseBlock], courseId: String) async { + let deleteHandler = deleteState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteHandler = deleteHandler { + await deleteHandler(blocks, courseId) + } + + } + + private let downloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadTaskCallCount: Int { + return downloadTaskState.withLock(\.callCount) + } + public var downloadTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadTaskState.withLock(\.handler) } + set { downloadTaskState.withLock { $0.handler = newValue } } + } + public func downloadTask(for blockId: String) async -> DownloadDataTask? { + let downloadTaskHandler = downloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadTaskHandler = downloadTaskHandler { + return await downloadTaskHandler(blockId) + } + return nil + } + + private let getFreeDiskSpaceState = MockoloMutex(MockoloHandlerState Int?>()) + public var getFreeDiskSpaceCallCount: Int { + return getFreeDiskSpaceState.withLock(\.callCount) + } + public var getFreeDiskSpaceHandler: (@Sendable () -> Int?)? { + get { getFreeDiskSpaceState.withLock(\.handler) } + set { getFreeDiskSpaceState.withLock { $0.handler = newValue } } + } + public func getFreeDiskSpace() -> Int? { + let getFreeDiskSpaceHandler = getFreeDiskSpaceState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getFreeDiskSpaceHandler = getFreeDiskSpaceHandler { + return getFreeDiskSpaceHandler() + } + return nil + } +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { + print("At \(function), the captured arguments are not Sendable, it is not concurrency-safe.") +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { +} + +/// Will be replaced to `Synchronization.Mutex` in future. +fileprivate final class MockoloMutex: @unchecked Sendable { + private let lock = NSLock() + private var value: Value + init(_ initialValue: Value) { + self.value = initialValue + } +#if compiler(>=6.0) + borrowing func withLock(_ body: (inout sending Value) throws(E) -> Result) throws(E) -> sending Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#else + func withLock(_ body: (inout Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#endif +} + +fileprivate struct MockoloUnsafeTransfer: @unchecked Sendable { + var value: Value + init(_ value: Value) { + self.value = value + } +} + +fileprivate struct MockoloHandlerState { + var argValues: [MockoloUnsafeTransfer] = [] + var handler: Handler? = nil + var callCount: Int = 0 +} + diff --git a/Core/Mockfile b/Core/Mockfile deleted file mode 100644 index 86cfe49c3..000000000 --- a/Core/Mockfile +++ /dev/null @@ -1,16 +0,0 @@ -sourceryCommand: mint run krzysztofzablocki/Sourcery@2.1.2 sourcery -sourceryTemplate: ../MockTemplate.swifttemplate -unit.tests.mock: - sources: - include: - - ./../Core - - ./Core - exclude: [] - output: ./CoreTests/CoreMock.generated.swift - targets: - - MyAppUnitTests - import: - - Core - - Foundation - - SwiftUI - - Combine \ No newline at end of file diff --git a/Course/Course.xcodeproj/project.pbxproj b/Course/Course.xcodeproj/project.pbxproj index a2c9717ef..ce171507d 100644 --- a/Course/Course.xcodeproj/project.pbxproj +++ b/Course/Course.xcodeproj/project.pbxproj @@ -23,7 +23,6 @@ 0231124D28EDA804002588FB /* CourseUnitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0231124C28EDA804002588FB /* CourseUnitView.swift */; }; 0231124F28EDA811002588FB /* CourseUnitViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0231124E28EDA811002588FB /* CourseUnitViewModel.swift */; }; 023812E8297AC8EB0087098F /* Course.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0289F8EE28E1C3510064F8F3 /* Course.framework */; platformFilter = ios; }; - 023812F3297AC9ED0087098F /* CourseMock.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023812F2297AC9EC0087098F /* CourseMock.generated.swift */; }; 02454CA02A2618E70043052A /* YouTubeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02454C9F2A2618E70043052A /* YouTubeView.swift */; }; 02454CA22A26190A0043052A /* EncodedVideoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02454CA12A26190A0043052A /* EncodedVideoView.swift */; }; 02454CA42A26193F0043052A /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02454CA32A26193F0043052A /* WebView.swift */; }; @@ -94,10 +93,11 @@ A52897DC2E276B12009C7044 /* CourseGradeCarouselSlideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52897DB2E276B02009C7044 /* CourseGradeCarouselSlideView.swift */; }; A52897DE2E277A7C009C7044 /* GradeItemCarouselView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52897DD2E277A7C009C7044 /* GradeItemCarouselView.swift */; }; A52897E02E278D7D009C7044 /* ViewAllButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52897DF2E278D7D009C7044 /* ViewAllButton.swift */; }; + A59016D52E69B2E900076220 /* VideoNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59016D42E69B2E900076220 /* VideoNavigationView.swift */; }; A5A510A22E66E8D600553607 /* CourseVideoCarouselSlideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A510A12E66E8D600553607 /* CourseVideoCarouselSlideView.swift */; }; A5A510A42E6728AD00553607 /* CourseAssignmentsCarouselSlideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A510A32E6728AD00553607 /* CourseAssignmentsCarouselSlideView.swift */; }; A5A510A62E672E4A00553607 /* AssignmentCarouselDetailCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A510A52E672E4A00553607 /* AssignmentCarouselDetailCardView.swift */; }; - A59016D52E69B2E900076220 /* VideoNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59016D42E69B2E900076220 /* VideoNavigationView.swift */; }; + A5B468142F29DCA3002A4ECA /* CourseMocks.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B468122F29DCA3002A4ECA /* CourseMocks.generated.swift */; }; B8F50317B6B830A0E520C954 /* Pods_App_Course_CourseTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50E59D2B81E12610964282C5 /* Pods_App_Course_CourseTests.framework */; }; BA58CF5D2B3D804D005B102E /* CourseStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA58CF5C2B3D804D005B102E /* CourseStorage.swift */; }; BA58CF612B471041005B102E /* VideoDownloadQualityBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA58CF602B471041005B102E /* VideoDownloadQualityBarView.swift */; }; @@ -191,7 +191,6 @@ 0231124C28EDA804002588FB /* CourseUnitView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseUnitView.swift; sourceTree = ""; }; 0231124E28EDA811002588FB /* CourseUnitViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseUnitViewModel.swift; sourceTree = ""; }; 023812E4297AC8EA0087098F /* CourseTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CourseTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 023812F2297AC9EC0087098F /* CourseMock.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CourseMock.generated.swift; sourceTree = ""; }; 02454C9F2A2618E70043052A /* YouTubeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YouTubeView.swift; sourceTree = ""; }; 02454CA12A26190A0043052A /* EncodedVideoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncodedVideoView.swift; sourceTree = ""; }; 02454CA32A26193F0043052A /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = ""; }; @@ -279,10 +278,11 @@ A52897DB2E276B02009C7044 /* CourseGradeCarouselSlideView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseGradeCarouselSlideView.swift; sourceTree = ""; }; A52897DD2E277A7C009C7044 /* GradeItemCarouselView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradeItemCarouselView.swift; sourceTree = ""; }; A52897DF2E278D7D009C7044 /* ViewAllButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewAllButton.swift; sourceTree = ""; }; + A59016D42E69B2E900076220 /* VideoNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoNavigationView.swift; sourceTree = ""; }; A5A510A12E66E8D600553607 /* CourseVideoCarouselSlideView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseVideoCarouselSlideView.swift; sourceTree = ""; }; A5A510A32E6728AD00553607 /* CourseAssignmentsCarouselSlideView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseAssignmentsCarouselSlideView.swift; sourceTree = ""; }; A5A510A52E672E4A00553607 /* AssignmentCarouselDetailCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssignmentCarouselDetailCardView.swift; sourceTree = ""; }; - A59016D42E69B2E900076220 /* VideoNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoNavigationView.swift; sourceTree = ""; }; + A5B468122F29DCA3002A4ECA /* CourseMocks.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseMocks.generated.swift; sourceTree = ""; }; ADC2A1B8183A674705F5F7E2 /* Pods-App-Course.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Course.debug.xcconfig"; path = "Target Support Files/Pods-App-Course/Pods-App-Course.debug.xcconfig"; sourceTree = ""; }; B196A14555D0E006995A5683 /* Pods-App-CourseDetails.releaseprod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-CourseDetails.releaseprod.xcconfig"; path = "Target Support Files/Pods-App-CourseDetails/Pods-App-CourseDetails.releaseprod.xcconfig"; sourceTree = ""; }; BA58CF5C2B3D804D005B102E /* CourseStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseStorage.swift; sourceTree = ""; }; @@ -383,8 +383,8 @@ 023812E5297AC8EB0087098F /* CourseTests */ = { isa = PBXGroup; children = ( + A5B468132F29DCA3002A4ECA /* Generated */, 0766DFD4299ADA3F00EBEF6A /* Presentation */, - 023812F2297AC9EC0087098F /* CourseMock.generated.swift */, ); path = CourseTests; sourceTree = ""; @@ -717,6 +717,14 @@ path = NewOutlIineAndProgress; sourceTree = ""; }; + A5B468132F29DCA3002A4ECA /* Generated */ = { + isa = PBXGroup; + children = ( + A5B468122F29DCA3002A4ECA /* CourseMocks.generated.swift */, + ); + path = Generated; + sourceTree = ""; + }; BA58CF622B471047005B102E /* VideoDownloadQualityBarView */ = { isa = PBXGroup; children = ( @@ -916,7 +924,6 @@ 023812E0297AC8EA0087098F /* Sources */, 023812E1297AC8EA0087098F /* Frameworks */, 023812E2297AC8EA0087098F /* Resources */, - 92C3B3183886DDECE1CBAC22 /* [CP] Copy Pods Resources */, CE7CAF432CC1563500E0AC9D /* Embed Frameworks */, ); buildRules = ( @@ -1031,23 +1038,6 @@ shellPath = /bin/sh; shellScript = "if [[ -f \"${PODS_ROOT}/SwiftGen/bin/swiftgen\" ]]; then\n \"${PODS_ROOT}/SwiftGen/bin/swiftgen\"\nelse\n echo \"warning: SwiftGen is not installed. Run 'pod install --repo-update' to install it.\"\nfi\n"; }; - 92C3B3183886DDECE1CBAC22 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Course-CourseTests/Pods-App-Course-CourseTests-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Course-CourseTests/Pods-App-Course-CourseTests-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App-Course-CourseTests/Pods-App-Course-CourseTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; B2836B9489F24D888A56D857 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1103,7 +1093,7 @@ 065D575D2D4442D700350351 /* CourseDownloadHelperTests.swift in Sources */, CE4BA8832E0806380050F2C7 /* CourseProgressViewModelTests.swift in Sources */, 02F78AEB29E6BCA20038DE30 /* VideoPlayerViewModelTests.swift in Sources */, - 023812F3297AC9ED0087098F /* CourseMock.generated.swift in Sources */, + A5B468142F29DCA3002A4ECA /* CourseMocks.generated.swift in Sources */, DB205BFB2AE81B1200136EC2 /* CourseDateViewModelTests.swift in Sources */, 022EA8CB297AD63B0014A8F7 /* CourseContainerViewModelTests.swift in Sources */, 0262148F29AE17C4008BD75A /* HandoutsViewModelTests.swift in Sources */, diff --git a/Course/Course/Data/CourseRepository.swift b/Course/Course/Data/CourseRepository.swift index 02db333ff..b33e2a134 100644 --- a/Course/Course/Data/CourseRepository.swift +++ b/Course/Course/Data/CourseRepository.swift @@ -9,6 +9,7 @@ import Foundation import Core import OEXFoundation +/// @mockable public protocol CourseRepositoryProtocol: Sendable { func getCourseBlocks(courseID: String) async throws -> CourseStructure func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure diff --git a/Course/Course/Data/CourseStorage.swift b/Course/Course/Data/CourseStorage.swift index c576b6279..aa582e12b 100644 --- a/Course/Course/Data/CourseStorage.swift +++ b/Course/Course/Data/CourseStorage.swift @@ -8,6 +8,7 @@ import Foundation import Core +/// @mockable public protocol CourseStorage: Sendable { var allowedDownloadLargeFile: Bool? { get set } var userSettings: UserSettings? { get set } diff --git a/Course/Course/Data/Persistence/CoursePersistenceProtocol.swift b/Course/Course/Data/Persistence/CoursePersistenceProtocol.swift index 7c404863f..46fc93834 100644 --- a/Course/Course/Data/Persistence/CoursePersistenceProtocol.swift +++ b/Course/Course/Data/Persistence/CoursePersistenceProtocol.swift @@ -8,6 +8,7 @@ import CoreData import Core +/// @mockable public protocol CoursePersistenceProtocol: Sendable { func loadEnrollments() async throws -> [Core.CourseItem] func saveEnrollments(items: [Core.CourseItem]) async diff --git a/Course/Course/Domain/CourseInteractor.swift b/Course/Course/Domain/CourseInteractor.swift index a21a8b5bd..0a38bb3f4 100644 --- a/Course/Course/Domain/CourseInteractor.swift +++ b/Course/Course/Domain/CourseInteractor.swift @@ -8,7 +8,7 @@ import Foundation import Core -//sourcery: AutoMockable +/// @mockable public protocol CourseInteractorProtocol: Sendable { func getCourseBlocks(courseID: String) async throws -> CourseStructure func getCourseVideoBlocks(fullStructure: CourseStructure) async -> CourseStructure diff --git a/Course/Course/Presentation/Container/CourseDownloadHelper.swift b/Course/Course/Presentation/Container/CourseDownloadHelper.swift index 1ddeb8e1b..f844ca262 100644 --- a/Course/Course/Presentation/Container/CourseDownloadHelper.swift +++ b/Course/Course/Presentation/Container/CourseDownloadHelper.swift @@ -9,7 +9,7 @@ import Combine import Core import Foundation -//sourcery: AutoMockable +/// @mockable public protocol CourseDownloadHelperProtocol: Sendable { var value: CourseDownloadValue? { get } var courseStructure: CourseStructure? { get set } diff --git a/Course/Course/Presentation/CourseAnalytics.swift b/Course/Course/Presentation/CourseAnalytics.swift index 4319fd820..c16a5c5d6 100644 --- a/Course/Course/Presentation/CourseAnalytics.swift +++ b/Course/Course/Presentation/CourseAnalytics.swift @@ -47,7 +47,7 @@ public enum SnackbarType: String { case updated } -//sourcery: AutoMockable +/// @mockable public protocol CourseAnalytics { func resumeCourseClicked(courseId: String, courseName: String, blockId: String) func sequentialClicked(courseId: String, courseName: String, blockId: String, blockName: String) diff --git a/Course/Course/Presentation/CourseRouter.swift b/Course/Course/Presentation/CourseRouter.swift index b1684874c..c46c6b6a3 100644 --- a/Course/Course/Presentation/CourseRouter.swift +++ b/Course/Course/Presentation/CourseRouter.swift @@ -8,6 +8,7 @@ import Foundation import Core +/// @mockable @MainActor public protocol CourseRouter: BaseRouter { diff --git a/Course/Course/Presentation/Video/PlayerServiceProtocol.swift b/Course/Course/Presentation/Video/PlayerServiceProtocol.swift index e632e3ebc..acc04b2ac 100644 --- a/Course/Course/Presentation/Video/PlayerServiceProtocol.swift +++ b/Course/Course/Presentation/Video/PlayerServiceProtocol.swift @@ -7,6 +7,7 @@ import SwiftUI +/// @mockable @MainActor public protocol PlayerServiceProtocol: Sendable { var router: CourseRouter { get } diff --git a/Course/Course/Presentation/Video/PlayerViewControllerHolder.swift b/Course/Course/Presentation/Video/PlayerViewControllerHolder.swift index d101cad70..8338403cb 100644 --- a/Course/Course/Presentation/Video/PlayerViewControllerHolder.swift +++ b/Course/Course/Presentation/Video/PlayerViewControllerHolder.swift @@ -9,6 +9,7 @@ @preconcurrency import Combine import Core +/// @mockable @MainActor public protocol PlayerViewControllerHolderProtocol: AnyObject, Sendable { var url: URL? { get } diff --git a/Course/CourseTests/CourseMock.generated.swift b/Course/CourseTests/CourseMock.generated.swift deleted file mode 100644 index 60be340b6..000000000 --- a/Course/CourseTests/CourseMock.generated.swift +++ /dev/null @@ -1,7087 +0,0 @@ -// Generated using Sourcery 2.1.2 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT - - -// Generated with SwiftyMocky 4.2.0 -// Required Sourcery: 1.8.0 - - -import SwiftyMocky -import XCTest -import Core -import Course -import Foundation -import SwiftUI -import Combine -import OEXFoundation - - -// MARK: - AuthInteractorProtocol - -open class AuthInteractorProtocolMock: AuthInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - @discardableResult - open func login(username: String, password: String) throws -> User { - addInvocation(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) - let perform = methodPerformValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) as? (String, String) -> Void - perform?(`username`, `password`) - var __value: User - do { - __value = try methodReturnValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(username: String, password: String). Use given") - Failure("Stub return value not specified for login(username: String, password: String). Use given") - } catch { - throw error - } - return __value - } - - @discardableResult - open func login(externalToken: String, backend: String) throws -> User { - addInvocation(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) - let perform = methodPerformValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) as? (String, String) -> Void - perform?(`externalToken`, `backend`) - var __value: User - do { - __value = try methodReturnValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - Failure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - } catch { - throw error - } - return __value - } - - open func login(ssoToken: String) throws -> User { - addInvocation(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) - let perform = methodPerformValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) as? (String) -> Void - perform?(`ssoToken`) - var __value: User - do { - __value = try methodReturnValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(ssoToken: String). Use given") - Failure("Stub return value not specified for login(ssoToken: String). Use given") - } catch { - throw error - } - return __value - } - - open func resetPassword(email: String) throws -> ResetPassword { - addInvocation(.m_resetPassword__email_email(Parameter.value(`email`))) - let perform = methodPerformValue(.m_resetPassword__email_email(Parameter.value(`email`))) as? (String) -> Void - perform?(`email`) - var __value: ResetPassword - do { - __value = try methodReturnValue(.m_resetPassword__email_email(Parameter.value(`email`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for resetPassword(email: String). Use given") - Failure("Stub return value not specified for resetPassword(email: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCookies(force: Bool) throws { - addInvocation(.m_getCookies__force_force(Parameter.value(`force`))) - let perform = methodPerformValue(.m_getCookies__force_force(Parameter.value(`force`))) as? (Bool) -> Void - perform?(`force`) - do { - _ = try methodReturnValue(.m_getCookies__force_force(Parameter.value(`force`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getRegistrationFields() throws -> [PickerFields] { - addInvocation(.m_getRegistrationFields) - let perform = methodPerformValue(.m_getRegistrationFields) as? () -> Void - perform?() - var __value: [PickerFields] - do { - __value = try methodReturnValue(.m_getRegistrationFields).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getRegistrationFields(). Use given") - Failure("Stub return value not specified for getRegistrationFields(). Use given") - } catch { - throw error - } - return __value - } - - open func registerUser(fields: [String: String], isSocial: Bool) throws -> User { - addInvocation(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) - let perform = methodPerformValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) as? ([String: String], Bool) -> Void - perform?(`fields`, `isSocial`) - var __value: User - do { - __value = try methodReturnValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - Failure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - } catch { - throw error - } - return __value - } - - open func validateRegistrationFields(fields: [String: String]) throws -> [String: String] { - addInvocation(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) - let perform = methodPerformValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) as? ([String: String]) -> Void - perform?(`fields`) - var __value: [String: String] - do { - __value = try methodReturnValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - Failure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_login__username_usernamepassword_password(Parameter, Parameter) - case m_login__externalToken_externalTokenbackend_backend(Parameter, Parameter) - case m_login__ssoToken_ssoToken(Parameter) - case m_resetPassword__email_email(Parameter) - case m_getCookies__force_force(Parameter) - case m_getRegistrationFields - case m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>, Parameter) - case m_validateRegistrationFields__fields_fields(Parameter<[String: String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_login__username_usernamepassword_password(let lhsUsername, let lhsPassword), .m_login__username_usernamepassword_password(let rhsUsername, let rhsPassword)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsername, rhs: rhsUsername, with: matcher), lhsUsername, rhsUsername, "username")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPassword, rhs: rhsPassword, with: matcher), lhsPassword, rhsPassword, "password")) - return Matcher.ComparisonResult(results) - - case (.m_login__externalToken_externalTokenbackend_backend(let lhsExternaltoken, let lhsBackend), .m_login__externalToken_externalTokenbackend_backend(let rhsExternaltoken, let rhsBackend)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsExternaltoken, rhs: rhsExternaltoken, with: matcher), lhsExternaltoken, rhsExternaltoken, "externalToken")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBackend, rhs: rhsBackend, with: matcher), lhsBackend, rhsBackend, "backend")) - return Matcher.ComparisonResult(results) - - case (.m_login__ssoToken_ssoToken(let lhsSsotoken), .m_login__ssoToken_ssoToken(let rhsSsotoken)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSsotoken, rhs: rhsSsotoken, with: matcher), lhsSsotoken, rhsSsotoken, "ssoToken")) - return Matcher.ComparisonResult(results) - - case (.m_resetPassword__email_email(let lhsEmail), .m_resetPassword__email_email(let rhsEmail)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEmail, rhs: rhsEmail, with: matcher), lhsEmail, rhsEmail, "email")) - return Matcher.ComparisonResult(results) - - case (.m_getCookies__force_force(let lhsForce), .m_getCookies__force_force(let rhsForce)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsForce, rhs: rhsForce, with: matcher), lhsForce, rhsForce, "force")) - return Matcher.ComparisonResult(results) - - case (.m_getRegistrationFields, .m_getRegistrationFields): return .match - - case (.m_registerUser__fields_fieldsisSocial_isSocial(let lhsFields, let lhsIssocial), .m_registerUser__fields_fieldsisSocial_isSocial(let rhsFields, let rhsIssocial)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIssocial, rhs: rhsIssocial, with: matcher), lhsIssocial, rhsIssocial, "isSocial")) - return Matcher.ComparisonResult(results) - - case (.m_validateRegistrationFields__fields_fields(let lhsFields), .m_validateRegistrationFields__fields_fields(let rhsFields)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_login__username_usernamepassword_password(p0, p1): return p0.intValue + p1.intValue - case let .m_login__externalToken_externalTokenbackend_backend(p0, p1): return p0.intValue + p1.intValue - case let .m_login__ssoToken_ssoToken(p0): return p0.intValue - case let .m_resetPassword__email_email(p0): return p0.intValue - case let .m_getCookies__force_force(p0): return p0.intValue - case .m_getRegistrationFields: return 0 - case let .m_registerUser__fields_fieldsisSocial_isSocial(p0, p1): return p0.intValue + p1.intValue - case let .m_validateRegistrationFields__fields_fields(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_login__username_usernamepassword_password: return ".login(username:password:)" - case .m_login__externalToken_externalTokenbackend_backend: return ".login(externalToken:backend:)" - case .m_login__ssoToken_ssoToken: return ".login(ssoToken:)" - case .m_resetPassword__email_email: return ".resetPassword(email:)" - case .m_getCookies__force_force: return ".getCookies(force:)" - case .m_getRegistrationFields: return ".getRegistrationFields()" - case .m_registerUser__fields_fieldsisSocial_isSocial: return ".registerUser(fields:isSocial:)" - case .m_validateRegistrationFields__fields_fields: return ".validateRegistrationFields(fields:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - @discardableResult - public static func login(username: Parameter, password: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func login(ssoToken: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func resetPassword(email: Parameter, willReturn: ResetPassword...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getRegistrationFields(willReturn: [PickerFields]...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willReturn: [String: String]...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func login(ssoToken: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func login(ssoToken: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func resetPassword(email: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resetPassword(email: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (ResetPassword).self) - willProduce(stubber) - return given - } - public static func getCookies(force: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCookies(force: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func getRegistrationFields(willThrow: Error...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getRegistrationFields(willProduce: (StubberThrows<[PickerFields]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([PickerFields]).self) - willProduce(stubber) - return given - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willProduce: (StubberThrows<[String: String]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([String: String]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - @discardableResult - public static func login(username: Parameter, password: Parameter) -> Verify { return Verify(method: .m_login__username_usernamepassword_password(`username`, `password`))} - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter) -> Verify { return Verify(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`))} - public static func login(ssoToken: Parameter) -> Verify { return Verify(method: .m_login__ssoToken_ssoToken(`ssoToken`))} - public static func resetPassword(email: Parameter) -> Verify { return Verify(method: .m_resetPassword__email_email(`email`))} - public static func getCookies(force: Parameter) -> Verify { return Verify(method: .m_getCookies__force_force(`force`))} - public static func getRegistrationFields() -> Verify { return Verify(method: .m_getRegistrationFields)} - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter) -> Verify { return Verify(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`))} - public static func validateRegistrationFields(fields: Parameter<[String: String]>) -> Verify { return Verify(method: .m_validateRegistrationFields__fields_fields(`fields`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - @discardableResult - public static func login(username: Parameter, password: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__username_usernamepassword_password(`username`, `password`), performs: perform) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), performs: perform) - } - public static func login(ssoToken: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_login__ssoToken_ssoToken(`ssoToken`), performs: perform) - } - public static func resetPassword(email: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_resetPassword__email_email(`email`), performs: perform) - } - public static func getCookies(force: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_getCookies__force_force(`force`), performs: perform) - } - public static func getRegistrationFields(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getRegistrationFields, performs: perform) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, perform: @escaping ([String: String], Bool) -> Void) -> Perform { - return Perform(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), performs: perform) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, perform: @escaping ([String: String]) -> Void) -> Perform { - return Perform(method: .m_validateRegistrationFields__fields_fields(`fields`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - BaseRouter -@MainActor -open class BaseRouterMock: BaseRouter, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func backToRoot(animated: Bool) { - addInvocation(.m_backToRoot__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_backToRoot__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func back(animated: Bool) { - addInvocation(.m_back__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_back__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func backWithFade() { - addInvocation(.m_backWithFade) - let perform = methodPerformValue(.m_backWithFade) as? () -> Void - perform?() - } - - open func dismiss(animated: Bool) { - addInvocation(.m_dismiss__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_dismiss__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func removeLastView(controllers: Int) { - addInvocation(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) - let perform = methodPerformValue(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) as? (Int) -> Void - perform?(`controllers`) - } - - open func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { - addInvocation(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) - let perform = methodPerformValue(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) as? (LogistrationSourceScreen, PostLoginData?) -> Void - perform?(`sourceScreen`, `postLoginData`) - } - - open func showStartupScreen() { - addInvocation(.m_showStartupScreen) - let perform = methodPerformValue(.m_showStartupScreen) as? () -> Void - perform?() - } - - open func showLoginScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showForgotPasswordScreen() { - addInvocation(.m_showForgotPasswordScreen) - let perform = methodPerformValue(.m_showForgotPasswordScreen) as? () -> Void - perform?() - } - - open func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) as? (String?, LogistrationSourceScreen) -> Void - perform?(`searchQuery`, `sourceScreen`) - } - - open func showWebBrowser(title: String, url: URL) { - addInvocation(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) - let perform = methodPerformValue(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) as? (String, URL) -> Void - perform?(`title`, `url`) - } - - open func showSSOWebBrowser(title: String) { - addInvocation(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) - let perform = methodPerformValue(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) as? (String) -> Void - perform?(`title`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) as? (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void - perform?(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) as? (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void - perform?(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { - addInvocation(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) as? (UIModalTransitionStyle, any View, (() -> Void)?) -> Void - perform?(`transitionStyle`, `view`, `completion`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { - addInvocation(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) as? (UIModalTransitionStyle, Bool, () -> any View) -> Void - perform?(`transitionStyle`, `animated`, `content`) - } - - - fileprivate enum MethodType { - case m_backToRoot__animated_animated(Parameter) - case m_back__animated_animated(Parameter) - case m_backWithFade - case m_dismiss__animated_animated(Parameter) - case m_removeLastView__controllers_controllers(Parameter) - case m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter, Parameter) - case m_showStartupScreen - case m_showLoginScreen__sourceScreen_sourceScreen(Parameter) - case m_showRegisterScreen__sourceScreen_sourceScreen(Parameter) - case m_showForgotPasswordScreen - case m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter, Parameter) - case m_showWebBrowser__title_titleurl_url(Parameter, Parameter) - case m_showSSOWebBrowser__title_title(Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter<() -> Void>) - case m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter, Parameter, Parameter<(() -> Void)?>) - case m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter, Parameter, Parameter<() -> any View>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_backToRoot__animated_animated(let lhsAnimated), .m_backToRoot__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_back__animated_animated(let lhsAnimated), .m_back__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_backWithFade, .m_backWithFade): return .match - - case (.m_dismiss__animated_animated(let lhsAnimated), .m_dismiss__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_removeLastView__controllers_controllers(let lhsControllers), .m_removeLastView__controllers_controllers(let rhsControllers)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsControllers, rhs: rhsControllers, with: matcher), lhsControllers, rhsControllers, "controllers")) - return Matcher.ComparisonResult(results) - - case (.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let lhsSourcescreen, let lhsPostlogindata), .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let rhsSourcescreen, let rhsPostlogindata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPostlogindata, rhs: rhsPostlogindata, with: matcher), lhsPostlogindata, rhsPostlogindata, "postLoginData")) - return Matcher.ComparisonResult(results) - - case (.m_showStartupScreen, .m_showStartupScreen): return .match - - case (.m_showLoginScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showLoginScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showRegisterScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showRegisterScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showForgotPasswordScreen, .m_showForgotPasswordScreen): return .match - - case (.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let lhsSearchquery, let lhsSourcescreen), .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let rhsSearchquery, let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchquery, rhs: rhsSearchquery, with: matcher), lhsSearchquery, rhsSearchquery, "searchQuery")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showWebBrowser__title_titleurl_url(let lhsTitle, let lhsUrl), .m_showWebBrowser__title_titleurl_url(let rhsTitle, let rhsUrl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - return Matcher.ComparisonResult(results) - - case (.m_showSSOWebBrowser__title_title(let lhsTitle), .m_showSSOWebBrowser__title_title(let rhsTitle)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let lhsAlerttitle, let lhsAlertmessage, let lhsPositiveaction, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsType), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let rhsAlerttitle, let rhsAlertmessage, let rhsPositiveaction, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPositiveaction, rhs: rhsPositiveaction, with: matcher), lhsPositiveaction, rhsPositiveaction, "positiveAction")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let lhsAlerttitle, let lhsAlertmessage, let lhsNextsectionname, let lhsAction, let lhsImage, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsNextsectiontapped), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let rhsAlerttitle, let rhsAlertmessage, let rhsNextsectionname, let rhsAction, let rhsImage, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsNextsectiontapped)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectionname, rhs: rhsNextsectionname, with: matcher), lhsNextsectionname, rhsNextsectionname, "nextSectionName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsImage, rhs: rhsImage, with: matcher), lhsImage, rhsImage, "image")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectiontapped, rhs: rhsNextsectiontapped, with: matcher), lhsNextsectiontapped, rhsNextsectiontapped, "nextSectionTapped")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let lhsTransitionstyle, let lhsView, let lhsCompletion), .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let rhsTransitionstyle, let rhsView, let rhsCompletion)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsView, rhs: rhsView, with: matcher), lhsView, rhsView, "view")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCompletion, rhs: rhsCompletion, with: matcher), lhsCompletion, rhsCompletion, "completion")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let lhsTransitionstyle, let lhsAnimated, let lhsContent), .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let rhsTransitionstyle, let rhsAnimated, let rhsContent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsContent, rhs: rhsContent, with: matcher), lhsContent, rhsContent, "content")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_backToRoot__animated_animated(p0): return p0.intValue - case let .m_back__animated_animated(p0): return p0.intValue - case .m_backWithFade: return 0 - case let .m_dismiss__animated_animated(p0): return p0.intValue - case let .m_removeLastView__controllers_controllers(p0): return p0.intValue - case let .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(p0, p1): return p0.intValue + p1.intValue - case .m_showStartupScreen: return 0 - case let .m_showLoginScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case let .m_showRegisterScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case .m_showForgotPasswordScreen: return 0 - case let .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(p0, p1): return p0.intValue + p1.intValue - case let .m_showWebBrowser__title_titleurl_url(p0, p1): return p0.intValue + p1.intValue - case let .m_showSSOWebBrowser__title_title(p0): return p0.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(p0, p1, p2, p3, p4, p5, p6, p7): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue + p7.intValue - case let .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_backToRoot__animated_animated: return ".backToRoot(animated:)" - case .m_back__animated_animated: return ".back(animated:)" - case .m_backWithFade: return ".backWithFade()" - case .m_dismiss__animated_animated: return ".dismiss(animated:)" - case .m_removeLastView__controllers_controllers: return ".removeLastView(controllers:)" - case .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData: return ".showMainOrWhatsNewScreen(sourceScreen:postLoginData:)" - case .m_showStartupScreen: return ".showStartupScreen()" - case .m_showLoginScreen__sourceScreen_sourceScreen: return ".showLoginScreen(sourceScreen:)" - case .m_showRegisterScreen__sourceScreen_sourceScreen: return ".showRegisterScreen(sourceScreen:)" - case .m_showForgotPasswordScreen: return ".showForgotPasswordScreen()" - case .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen: return ".showDiscoveryScreen(searchQuery:sourceScreen:)" - case .m_showWebBrowser__title_titleurl_url: return ".showWebBrowser(title:url:)" - case .m_showSSOWebBrowser__title_title: return ".showSSOWebBrowser(title:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type: return ".presentAlert(alertTitle:alertMessage:positiveAction:onCloseTapped:firstButtonTapped:type:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped: return ".presentAlert(alertTitle:alertMessage:nextSectionName:action:image:onCloseTapped:firstButtonTapped:nextSectionTapped:)" - case .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion: return ".presentView(transitionStyle:view:completion:)" - case .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content: return ".presentView(transitionStyle:animated:content:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func backToRoot(animated: Parameter) -> Verify { return Verify(method: .m_backToRoot__animated_animated(`animated`))} - public static func back(animated: Parameter) -> Verify { return Verify(method: .m_back__animated_animated(`animated`))} - public static func backWithFade() -> Verify { return Verify(method: .m_backWithFade)} - public static func dismiss(animated: Parameter) -> Verify { return Verify(method: .m_dismiss__animated_animated(`animated`))} - public static func removeLastView(controllers: Parameter) -> Verify { return Verify(method: .m_removeLastView__controllers_controllers(`controllers`))} - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter) -> Verify { return Verify(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`))} - public static func showStartupScreen() -> Verify { return Verify(method: .m_showStartupScreen)} - public static func showLoginScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showRegisterScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showForgotPasswordScreen() -> Verify { return Verify(method: .m_showForgotPasswordScreen)} - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter) -> Verify { return Verify(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`))} - public static func showWebBrowser(title: Parameter, url: Parameter) -> Verify { return Verify(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`))} - public static func showSSOWebBrowser(title: Parameter) -> Verify { return Verify(method: .m_showSSOWebBrowser__title_title(`title`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`))} - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`))} - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func backToRoot(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_backToRoot__animated_animated(`animated`), performs: perform) - } - public static func back(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_back__animated_animated(`animated`), performs: perform) - } - public static func backWithFade(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_backWithFade, performs: perform) - } - public static func dismiss(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_dismiss__animated_animated(`animated`), performs: perform) - } - public static func removeLastView(controllers: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_removeLastView__controllers_controllers(`controllers`), performs: perform) - } - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter, perform: @escaping (LogistrationSourceScreen, PostLoginData?) -> Void) -> Perform { - return Perform(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`), performs: perform) - } - public static func showStartupScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showStartupScreen, performs: perform) - } - public static func showLoginScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showRegisterScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showForgotPasswordScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showForgotPasswordScreen, performs: perform) - } - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter, perform: @escaping (String?, LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`), performs: perform) - } - public static func showWebBrowser(title: Parameter, url: Parameter, perform: @escaping (String, URL) -> Void) -> Perform { - return Perform(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`), performs: perform) - } - public static func showSSOWebBrowser(title: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showSSOWebBrowser__title_title(`title`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter, perform: @escaping (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>, perform: @escaping (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>, perform: @escaping (UIModalTransitionStyle, any View, (() -> Void)?) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>, perform: @escaping (UIModalTransitionStyle, Bool, () -> any View) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CalendarManagerProtocol -@MainActor -open class CalendarManagerProtocolMock: CalendarManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func createCalendarIfNeeded() { - addInvocation(.m_createCalendarIfNeeded) - let perform = methodPerformValue(.m_createCalendarIfNeeded) as? () -> Void - perform?() - } - - open func filterCoursesBySelected(fetchedCourses: [CourseForSync]) -> [CourseForSync] { - addInvocation(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) - let perform = methodPerformValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) as? ([CourseForSync]) -> Void - perform?(`fetchedCourses`) - var __value: [CourseForSync] - do { - __value = try methodReturnValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))).casted() - } catch { - onFatalFailure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - Failure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - } - return __value - } - - open func removeOldCalendar() { - addInvocation(.m_removeOldCalendar) - let perform = methodPerformValue(.m_removeOldCalendar) as? () -> Void - perform?() - } - - open func removeOutdatedEvents(courseID: String) { - addInvocation(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - } - - open func syncCourse(courseID: String, courseName: String, dates: CourseDates) { - addInvocation(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) - let perform = methodPerformValue(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) as? (String, String, CourseDates) -> Void - perform?(`courseID`, `courseName`, `dates`) - } - - open func requestAccess() -> Bool { - addInvocation(.m_requestAccess) - let perform = methodPerformValue(.m_requestAccess) as? () -> Void - perform?() - var __value: Bool - do { - __value = try methodReturnValue(.m_requestAccess).casted() - } catch { - onFatalFailure("Stub return value not specified for requestAccess(). Use given") - Failure("Stub return value not specified for requestAccess(). Use given") - } - return __value - } - - open func courseStatus(courseID: String) -> SyncStatus { - addInvocation(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: SyncStatus - do { - __value = try methodReturnValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for courseStatus(courseID: String). Use given") - Failure("Stub return value not specified for courseStatus(courseID: String). Use given") - } - return __value - } - - open func clearAllData(removeCalendar: Bool) { - addInvocation(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) - let perform = methodPerformValue(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) as? (Bool) -> Void - perform?(`removeCalendar`) - } - - open func isDatesChanged(courseID: String, checksum: String) -> Bool { - addInvocation(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) - let perform = methodPerformValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) as? (String, String) -> Void - perform?(`courseID`, `checksum`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - Failure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - } - return __value - } - - - fileprivate enum MethodType { - case m_createCalendarIfNeeded - case m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>) - case m_removeOldCalendar - case m_removeOutdatedEvents__courseID_courseID(Parameter) - case m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter, Parameter, Parameter) - case m_requestAccess - case m_courseStatus__courseID_courseID(Parameter) - case m_clearAllData__removeCalendar_removeCalendar(Parameter) - case m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_createCalendarIfNeeded, .m_createCalendarIfNeeded): return .match - - case (.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let lhsFetchedcourses), .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let rhsFetchedcourses)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFetchedcourses, rhs: rhsFetchedcourses, with: matcher), lhsFetchedcourses, rhsFetchedcourses, "fetchedCourses")) - return Matcher.ComparisonResult(results) - - case (.m_removeOldCalendar, .m_removeOldCalendar): return .match - - case (.m_removeOutdatedEvents__courseID_courseID(let lhsCourseid), .m_removeOutdatedEvents__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let lhsCourseid, let lhsCoursename, let lhsDates), .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let rhsCourseid, let rhsCoursename, let rhsDates)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDates, rhs: rhsDates, with: matcher), lhsDates, rhsDates, "dates")) - return Matcher.ComparisonResult(results) - - case (.m_requestAccess, .m_requestAccess): return .match - - case (.m_courseStatus__courseID_courseID(let lhsCourseid), .m_courseStatus__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_clearAllData__removeCalendar_removeCalendar(let lhsRemovecalendar), .m_clearAllData__removeCalendar_removeCalendar(let rhsRemovecalendar)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRemovecalendar, rhs: rhsRemovecalendar, with: matcher), lhsRemovecalendar, rhsRemovecalendar, "removeCalendar")) - return Matcher.ComparisonResult(results) - - case (.m_isDatesChanged__courseID_courseIDchecksum_checksum(let lhsCourseid, let lhsChecksum), .m_isDatesChanged__courseID_courseIDchecksum_checksum(let rhsCourseid, let rhsChecksum)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsChecksum, rhs: rhsChecksum, with: matcher), lhsChecksum, rhsChecksum, "checksum")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_createCalendarIfNeeded: return 0 - case let .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(p0): return p0.intValue - case .m_removeOldCalendar: return 0 - case let .m_removeOutdatedEvents__courseID_courseID(p0): return p0.intValue - case let .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case .m_requestAccess: return 0 - case let .m_courseStatus__courseID_courseID(p0): return p0.intValue - case let .m_clearAllData__removeCalendar_removeCalendar(p0): return p0.intValue - case let .m_isDatesChanged__courseID_courseIDchecksum_checksum(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_createCalendarIfNeeded: return ".createCalendarIfNeeded()" - case .m_filterCoursesBySelected__fetchedCourses_fetchedCourses: return ".filterCoursesBySelected(fetchedCourses:)" - case .m_removeOldCalendar: return ".removeOldCalendar()" - case .m_removeOutdatedEvents__courseID_courseID: return ".removeOutdatedEvents(courseID:)" - case .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates: return ".syncCourse(courseID:courseName:dates:)" - case .m_requestAccess: return ".requestAccess()" - case .m_courseStatus__courseID_courseID: return ".courseStatus(courseID:)" - case .m_clearAllData__removeCalendar_removeCalendar: return ".clearAllData(removeCalendar:)" - case .m_isDatesChanged__courseID_courseIDchecksum_checksum: return ".isDatesChanged(courseID:checksum:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willReturn: [CourseForSync]...) -> MethodStub { - return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func requestAccess(willReturn: Bool...) -> MethodStub { - return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func courseStatus(courseID: Parameter, willReturn: SyncStatus...) -> MethodStub { - return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willProduce: (Stubber<[CourseForSync]>) -> Void) -> MethodStub { - let willReturn: [[CourseForSync]] = [] - let given: Given = { return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([CourseForSync]).self) - willProduce(stubber) - return given - } - public static func requestAccess(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func courseStatus(courseID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [SyncStatus] = [] - let given: Given = { return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (SyncStatus).self) - willProduce(stubber) - return given - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func createCalendarIfNeeded() -> Verify { return Verify(method: .m_createCalendarIfNeeded)} - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>) -> Verify { return Verify(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`))} - public static func removeOldCalendar() -> Verify { return Verify(method: .m_removeOldCalendar)} - public static func removeOutdatedEvents(courseID: Parameter) -> Verify { return Verify(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`))} - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter) -> Verify { return Verify(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`))} - public static func requestAccess() -> Verify { return Verify(method: .m_requestAccess)} - public static func courseStatus(courseID: Parameter) -> Verify { return Verify(method: .m_courseStatus__courseID_courseID(`courseID`))} - public static func clearAllData(removeCalendar: Parameter) -> Verify { return Verify(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`))} - public static func isDatesChanged(courseID: Parameter, checksum: Parameter) -> Verify { return Verify(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func createCalendarIfNeeded(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_createCalendarIfNeeded, performs: perform) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, perform: @escaping ([CourseForSync]) -> Void) -> Perform { - return Perform(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), performs: perform) - } - public static func removeOldCalendar(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeOldCalendar, performs: perform) - } - public static func removeOutdatedEvents(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`), performs: perform) - } - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter, perform: @escaping (String, String, CourseDates) -> Void) -> Perform { - return Perform(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`), performs: perform) - } - public static func requestAccess(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_requestAccess, performs: perform) - } - public static func courseStatus(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_courseStatus__courseID_courseID(`courseID`), performs: perform) - } - public static func clearAllData(removeCalendar: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`), performs: perform) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConfigProtocol - -open class ConfigProtocolMock: ConfigProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var baseURL: URL { - get { invocations.append(.p_baseURL_get); return __p_baseURL ?? givenGetterValue(.p_baseURL_get, "ConfigProtocolMock - stub value for baseURL was not defined") } - } - private var __p_baseURL: (URL)? - - public var baseSSOURL: URL { - get { invocations.append(.p_baseSSOURL_get); return __p_baseSSOURL ?? givenGetterValue(.p_baseSSOURL_get, "ConfigProtocolMock - stub value for baseSSOURL was not defined") } - } - private var __p_baseSSOURL: (URL)? - - public var ssoFinishedURL: URL { - get { invocations.append(.p_ssoFinishedURL_get); return __p_ssoFinishedURL ?? givenGetterValue(.p_ssoFinishedURL_get, "ConfigProtocolMock - stub value for ssoFinishedURL was not defined") } - } - private var __p_ssoFinishedURL: (URL)? - - public var ssoButtonTitle: [String: Any] { - get { invocations.append(.p_ssoButtonTitle_get); return __p_ssoButtonTitle ?? givenGetterValue(.p_ssoButtonTitle_get, "ConfigProtocolMock - stub value for ssoButtonTitle was not defined") } - } - private var __p_ssoButtonTitle: ([String: Any])? - - public var oAuthClientId: String { - get { invocations.append(.p_oAuthClientId_get); return __p_oAuthClientId ?? givenGetterValue(.p_oAuthClientId_get, "ConfigProtocolMock - stub value for oAuthClientId was not defined") } - } - private var __p_oAuthClientId: (String)? - - public var tokenType: TokenType { - get { invocations.append(.p_tokenType_get); return __p_tokenType ?? givenGetterValue(.p_tokenType_get, "ConfigProtocolMock - stub value for tokenType was not defined") } - } - private var __p_tokenType: (TokenType)? - - public var feedbackEmail: String { - get { invocations.append(.p_feedbackEmail_get); return __p_feedbackEmail ?? givenGetterValue(.p_feedbackEmail_get, "ConfigProtocolMock - stub value for feedbackEmail was not defined") } - } - private var __p_feedbackEmail: (String)? - - public var appStoreLink: String { - get { invocations.append(.p_appStoreLink_get); return __p_appStoreLink ?? givenGetterValue(.p_appStoreLink_get, "ConfigProtocolMock - stub value for appStoreLink was not defined") } - } - private var __p_appStoreLink: (String)? - - public var faq: URL? { - get { invocations.append(.p_faq_get); return __p_faq ?? optionalGivenGetterValue(.p_faq_get, "ConfigProtocolMock - stub value for faq was not defined") } - } - private var __p_faq: (URL)? - - public var platformName: String { - get { invocations.append(.p_platformName_get); return __p_platformName ?? givenGetterValue(.p_platformName_get, "ConfigProtocolMock - stub value for platformName was not defined") } - } - private var __p_platformName: (String)? - - public var agreement: AgreementConfig { - get { invocations.append(.p_agreement_get); return __p_agreement ?? givenGetterValue(.p_agreement_get, "ConfigProtocolMock - stub value for agreement was not defined") } - } - private var __p_agreement: (AgreementConfig)? - - public var firebase: FirebaseConfig { - get { invocations.append(.p_firebase_get); return __p_firebase ?? givenGetterValue(.p_firebase_get, "ConfigProtocolMock - stub value for firebase was not defined") } - } - private var __p_firebase: (FirebaseConfig)? - - public var facebook: FacebookConfig { - get { invocations.append(.p_facebook_get); return __p_facebook ?? givenGetterValue(.p_facebook_get, "ConfigProtocolMock - stub value for facebook was not defined") } - } - private var __p_facebook: (FacebookConfig)? - - public var microsoft: MicrosoftConfig { - get { invocations.append(.p_microsoft_get); return __p_microsoft ?? givenGetterValue(.p_microsoft_get, "ConfigProtocolMock - stub value for microsoft was not defined") } - } - private var __p_microsoft: (MicrosoftConfig)? - - public var google: GoogleConfig { - get { invocations.append(.p_google_get); return __p_google ?? givenGetterValue(.p_google_get, "ConfigProtocolMock - stub value for google was not defined") } - } - private var __p_google: (GoogleConfig)? - - public var appleSignIn: AppleSignInConfig { - get { invocations.append(.p_appleSignIn_get); return __p_appleSignIn ?? givenGetterValue(.p_appleSignIn_get, "ConfigProtocolMock - stub value for appleSignIn was not defined") } - } - private var __p_appleSignIn: (AppleSignInConfig)? - - public var features: FeaturesConfig { - get { invocations.append(.p_features_get); return __p_features ?? givenGetterValue(.p_features_get, "ConfigProtocolMock - stub value for features was not defined") } - } - private var __p_features: (FeaturesConfig)? - - public var theme: ThemeConfig { - get { invocations.append(.p_theme_get); return __p_theme ?? givenGetterValue(.p_theme_get, "ConfigProtocolMock - stub value for theme was not defined") } - } - private var __p_theme: (ThemeConfig)? - - public var uiComponents: UIComponentsConfig { - get { invocations.append(.p_uiComponents_get); return __p_uiComponents ?? givenGetterValue(.p_uiComponents_get, "ConfigProtocolMock - stub value for uiComponents was not defined") } - } - private var __p_uiComponents: (UIComponentsConfig)? - - public var discovery: DiscoveryConfig { - get { invocations.append(.p_discovery_get); return __p_discovery ?? givenGetterValue(.p_discovery_get, "ConfigProtocolMock - stub value for discovery was not defined") } - } - private var __p_discovery: (DiscoveryConfig)? - - public var dashboard: DashboardConfig { - get { invocations.append(.p_dashboard_get); return __p_dashboard ?? givenGetterValue(.p_dashboard_get, "ConfigProtocolMock - stub value for dashboard was not defined") } - } - private var __p_dashboard: (DashboardConfig)? - - public var braze: BrazeConfig { - get { invocations.append(.p_braze_get); return __p_braze ?? givenGetterValue(.p_braze_get, "ConfigProtocolMock - stub value for braze was not defined") } - } - private var __p_braze: (BrazeConfig)? - - public var branch: BranchConfig { - get { invocations.append(.p_branch_get); return __p_branch ?? givenGetterValue(.p_branch_get, "ConfigProtocolMock - stub value for branch was not defined") } - } - private var __p_branch: (BranchConfig)? - - public var program: DiscoveryConfig { - get { invocations.append(.p_program_get); return __p_program ?? givenGetterValue(.p_program_get, "ConfigProtocolMock - stub value for program was not defined") } - } - private var __p_program: (DiscoveryConfig)? - - public var experimentalFeatures: ExperimentalFeaturesConfig { - get { invocations.append(.p_experimentalFeatures_get); return __p_experimentalFeatures ?? givenGetterValue(.p_experimentalFeatures_get, "ConfigProtocolMock - stub value for experimentalFeatures was not defined") } - } - private var __p_experimentalFeatures: (ExperimentalFeaturesConfig)? - - public var URIScheme: String { - get { invocations.append(.p_URIScheme_get); return __p_URIScheme ?? givenGetterValue(.p_URIScheme_get, "ConfigProtocolMock - stub value for URIScheme was not defined") } - } - private var __p_URIScheme: (String)? - - - - - - - fileprivate enum MethodType { - case p_baseURL_get - case p_baseSSOURL_get - case p_ssoFinishedURL_get - case p_ssoButtonTitle_get - case p_oAuthClientId_get - case p_tokenType_get - case p_feedbackEmail_get - case p_appStoreLink_get - case p_faq_get - case p_platformName_get - case p_agreement_get - case p_firebase_get - case p_facebook_get - case p_microsoft_get - case p_google_get - case p_appleSignIn_get - case p_features_get - case p_theme_get - case p_uiComponents_get - case p_discovery_get - case p_dashboard_get - case p_braze_get - case p_branch_get - case p_program_get - case p_experimentalFeatures_get - case p_URIScheme_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_baseURL_get,.p_baseURL_get): return Matcher.ComparisonResult.match - case (.p_baseSSOURL_get,.p_baseSSOURL_get): return Matcher.ComparisonResult.match - case (.p_ssoFinishedURL_get,.p_ssoFinishedURL_get): return Matcher.ComparisonResult.match - case (.p_ssoButtonTitle_get,.p_ssoButtonTitle_get): return Matcher.ComparisonResult.match - case (.p_oAuthClientId_get,.p_oAuthClientId_get): return Matcher.ComparisonResult.match - case (.p_tokenType_get,.p_tokenType_get): return Matcher.ComparisonResult.match - case (.p_feedbackEmail_get,.p_feedbackEmail_get): return Matcher.ComparisonResult.match - case (.p_appStoreLink_get,.p_appStoreLink_get): return Matcher.ComparisonResult.match - case (.p_faq_get,.p_faq_get): return Matcher.ComparisonResult.match - case (.p_platformName_get,.p_platformName_get): return Matcher.ComparisonResult.match - case (.p_agreement_get,.p_agreement_get): return Matcher.ComparisonResult.match - case (.p_firebase_get,.p_firebase_get): return Matcher.ComparisonResult.match - case (.p_facebook_get,.p_facebook_get): return Matcher.ComparisonResult.match - case (.p_microsoft_get,.p_microsoft_get): return Matcher.ComparisonResult.match - case (.p_google_get,.p_google_get): return Matcher.ComparisonResult.match - case (.p_appleSignIn_get,.p_appleSignIn_get): return Matcher.ComparisonResult.match - case (.p_features_get,.p_features_get): return Matcher.ComparisonResult.match - case (.p_theme_get,.p_theme_get): return Matcher.ComparisonResult.match - case (.p_uiComponents_get,.p_uiComponents_get): return Matcher.ComparisonResult.match - case (.p_discovery_get,.p_discovery_get): return Matcher.ComparisonResult.match - case (.p_dashboard_get,.p_dashboard_get): return Matcher.ComparisonResult.match - case (.p_braze_get,.p_braze_get): return Matcher.ComparisonResult.match - case (.p_branch_get,.p_branch_get): return Matcher.ComparisonResult.match - case (.p_program_get,.p_program_get): return Matcher.ComparisonResult.match - case (.p_experimentalFeatures_get,.p_experimentalFeatures_get): return Matcher.ComparisonResult.match - case (.p_URIScheme_get,.p_URIScheme_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_baseURL_get: return 0 - case .p_baseSSOURL_get: return 0 - case .p_ssoFinishedURL_get: return 0 - case .p_ssoButtonTitle_get: return 0 - case .p_oAuthClientId_get: return 0 - case .p_tokenType_get: return 0 - case .p_feedbackEmail_get: return 0 - case .p_appStoreLink_get: return 0 - case .p_faq_get: return 0 - case .p_platformName_get: return 0 - case .p_agreement_get: return 0 - case .p_firebase_get: return 0 - case .p_facebook_get: return 0 - case .p_microsoft_get: return 0 - case .p_google_get: return 0 - case .p_appleSignIn_get: return 0 - case .p_features_get: return 0 - case .p_theme_get: return 0 - case .p_uiComponents_get: return 0 - case .p_discovery_get: return 0 - case .p_dashboard_get: return 0 - case .p_braze_get: return 0 - case .p_branch_get: return 0 - case .p_program_get: return 0 - case .p_experimentalFeatures_get: return 0 - case .p_URIScheme_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_baseURL_get: return "[get] .baseURL" - case .p_baseSSOURL_get: return "[get] .baseSSOURL" - case .p_ssoFinishedURL_get: return "[get] .ssoFinishedURL" - case .p_ssoButtonTitle_get: return "[get] .ssoButtonTitle" - case .p_oAuthClientId_get: return "[get] .oAuthClientId" - case .p_tokenType_get: return "[get] .tokenType" - case .p_feedbackEmail_get: return "[get] .feedbackEmail" - case .p_appStoreLink_get: return "[get] .appStoreLink" - case .p_faq_get: return "[get] .faq" - case .p_platformName_get: return "[get] .platformName" - case .p_agreement_get: return "[get] .agreement" - case .p_firebase_get: return "[get] .firebase" - case .p_facebook_get: return "[get] .facebook" - case .p_microsoft_get: return "[get] .microsoft" - case .p_google_get: return "[get] .google" - case .p_appleSignIn_get: return "[get] .appleSignIn" - case .p_features_get: return "[get] .features" - case .p_theme_get: return "[get] .theme" - case .p_uiComponents_get: return "[get] .uiComponents" - case .p_discovery_get: return "[get] .discovery" - case .p_dashboard_get: return "[get] .dashboard" - case .p_braze_get: return "[get] .braze" - case .p_branch_get: return "[get] .branch" - case .p_program_get: return "[get] .program" - case .p_experimentalFeatures_get: return "[get] .experimentalFeatures" - case .p_URIScheme_get: return "[get] .URIScheme" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func baseURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func baseSSOURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseSSOURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoFinishedURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_ssoFinishedURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoButtonTitle(getter defaultValue: [String: Any]...) -> PropertyStub { - return Given(method: .p_ssoButtonTitle_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func oAuthClientId(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_oAuthClientId_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func tokenType(getter defaultValue: TokenType...) -> PropertyStub { - return Given(method: .p_tokenType_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func feedbackEmail(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_feedbackEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appStoreLink(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_appStoreLink_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func faq(getter defaultValue: URL?...) -> PropertyStub { - return Given(method: .p_faq_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func platformName(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_platformName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func agreement(getter defaultValue: AgreementConfig...) -> PropertyStub { - return Given(method: .p_agreement_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func firebase(getter defaultValue: FirebaseConfig...) -> PropertyStub { - return Given(method: .p_firebase_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func facebook(getter defaultValue: FacebookConfig...) -> PropertyStub { - return Given(method: .p_facebook_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func microsoft(getter defaultValue: MicrosoftConfig...) -> PropertyStub { - return Given(method: .p_microsoft_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func google(getter defaultValue: GoogleConfig...) -> PropertyStub { - return Given(method: .p_google_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignIn(getter defaultValue: AppleSignInConfig...) -> PropertyStub { - return Given(method: .p_appleSignIn_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func features(getter defaultValue: FeaturesConfig...) -> PropertyStub { - return Given(method: .p_features_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func theme(getter defaultValue: ThemeConfig...) -> PropertyStub { - return Given(method: .p_theme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func uiComponents(getter defaultValue: UIComponentsConfig...) -> PropertyStub { - return Given(method: .p_uiComponents_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func discovery(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_discovery_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func dashboard(getter defaultValue: DashboardConfig...) -> PropertyStub { - return Given(method: .p_dashboard_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func braze(getter defaultValue: BrazeConfig...) -> PropertyStub { - return Given(method: .p_braze_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func branch(getter defaultValue: BranchConfig...) -> PropertyStub { - return Given(method: .p_branch_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func program(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_program_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func experimentalFeatures(getter defaultValue: ExperimentalFeaturesConfig...) -> PropertyStub { - return Given(method: .p_experimentalFeatures_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func URIScheme(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_URIScheme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var baseURL: Verify { return Verify(method: .p_baseURL_get) } - public static var baseSSOURL: Verify { return Verify(method: .p_baseSSOURL_get) } - public static var ssoFinishedURL: Verify { return Verify(method: .p_ssoFinishedURL_get) } - public static var ssoButtonTitle: Verify { return Verify(method: .p_ssoButtonTitle_get) } - public static var oAuthClientId: Verify { return Verify(method: .p_oAuthClientId_get) } - public static var tokenType: Verify { return Verify(method: .p_tokenType_get) } - public static var feedbackEmail: Verify { return Verify(method: .p_feedbackEmail_get) } - public static var appStoreLink: Verify { return Verify(method: .p_appStoreLink_get) } - public static var faq: Verify { return Verify(method: .p_faq_get) } - public static var platformName: Verify { return Verify(method: .p_platformName_get) } - public static var agreement: Verify { return Verify(method: .p_agreement_get) } - public static var firebase: Verify { return Verify(method: .p_firebase_get) } - public static var facebook: Verify { return Verify(method: .p_facebook_get) } - public static var microsoft: Verify { return Verify(method: .p_microsoft_get) } - public static var google: Verify { return Verify(method: .p_google_get) } - public static var appleSignIn: Verify { return Verify(method: .p_appleSignIn_get) } - public static var features: Verify { return Verify(method: .p_features_get) } - public static var theme: Verify { return Verify(method: .p_theme_get) } - public static var uiComponents: Verify { return Verify(method: .p_uiComponents_get) } - public static var discovery: Verify { return Verify(method: .p_discovery_get) } - public static var dashboard: Verify { return Verify(method: .p_dashboard_get) } - public static var braze: Verify { return Verify(method: .p_braze_get) } - public static var branch: Verify { return Verify(method: .p_branch_get) } - public static var program: Verify { return Verify(method: .p_program_get) } - public static var experimentalFeatures: Verify { return Verify(method: .p_experimentalFeatures_get) } - public static var URIScheme: Verify { return Verify(method: .p_URIScheme_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConnectivityProtocol -@MainActor -open class ConnectivityProtocolMock: ConnectivityProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var isInternetAvaliable: Bool { - get { invocations.append(.p_isInternetAvaliable_get); return __p_isInternetAvaliable ?? givenGetterValue(.p_isInternetAvaliable_get, "ConnectivityProtocolMock - stub value for isInternetAvaliable was not defined") } - } - private var __p_isInternetAvaliable: (Bool)? - - public var isMobileData: Bool { - get { invocations.append(.p_isMobileData_get); return __p_isMobileData ?? givenGetterValue(.p_isMobileData_get, "ConnectivityProtocolMock - stub value for isMobileData was not defined") } - } - private var __p_isMobileData: (Bool)? - - public var internetReachableSubject: CurrentValueSubject { - get { invocations.append(.p_internetReachableSubject_get); return __p_internetReachableSubject ?? givenGetterValue(.p_internetReachableSubject_get, "ConnectivityProtocolMock - stub value for internetReachableSubject was not defined") } - } - private var __p_internetReachableSubject: (CurrentValueSubject)? - - - - - - - fileprivate enum MethodType { - case p_isInternetAvaliable_get - case p_isMobileData_get - case p_internetReachableSubject_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_isInternetAvaliable_get,.p_isInternetAvaliable_get): return Matcher.ComparisonResult.match - case (.p_isMobileData_get,.p_isMobileData_get): return Matcher.ComparisonResult.match - case (.p_internetReachableSubject_get,.p_internetReachableSubject_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_isInternetAvaliable_get: return 0 - case .p_isMobileData_get: return 0 - case .p_internetReachableSubject_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_isInternetAvaliable_get: return "[get] .isInternetAvaliable" - case .p_isMobileData_get: return "[get] .isMobileData" - case .p_internetReachableSubject_get: return "[get] .internetReachableSubject" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func isInternetAvaliable(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isInternetAvaliable_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func isMobileData(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isMobileData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func internetReachableSubject(getter defaultValue: CurrentValueSubject...) -> PropertyStub { - return Given(method: .p_internetReachableSubject_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var isInternetAvaliable: Verify { return Verify(method: .p_isInternetAvaliable_get) } - public static var isMobileData: Verify { return Verify(method: .p_isMobileData_get) } - public static var internetReachableSubject: Verify { return Verify(method: .p_internetReachableSubject_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreAnalytics - -open class CoreAnalyticsMock: CoreAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { - addInvocation(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) - let perform = methodPerformValue(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) as? (AnalyticsEvent, EventBIValue, String?, Int?) -> Void - perform?(`event`, `biValue`, `action`, `rating`) - } - - open func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { - addInvocation(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) - let perform = methodPerformValue(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) as? (AnalyticsEvent, EventBIValue, String, String) -> Void - perform?(`event`, `bivalue`, `value`, `oldValue`) - } - - open func trackEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackScreenEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackScreenEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - - fileprivate enum MethodType { - case m_trackEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter, Parameter, Parameter, Parameter) - case m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter, Parameter, Parameter, Parameter) - case m_trackEvent__event(Parameter) - case m_trackEvent__eventbiValue_biValue(Parameter, Parameter) - case m_trackScreenEvent__event(Parameter) - case m_trackScreenEvent__eventbiValue_biValue(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_trackEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackScreenEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_appreview__eventbiValue_biValueaction_actionrating_rating(let lhsEvent, let lhsBivalue, let lhsAction, let lhsRating), .m_appreview__eventbiValue_biValueaction_actionrating_rating(let rhsEvent, let rhsBivalue, let rhsAction, let rhsRating)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRating, rhs: rhsRating, with: matcher), lhsRating, rhsRating, "rating")) - return Matcher.ComparisonResult(results) - - case (.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let lhsEvent, let lhsBivalue, let lhsValue, let lhsOldvalue), .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let rhsEvent, let rhsBivalue, let rhsValue, let rhsOldvalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "bivalue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsValue, rhs: rhsValue, with: matcher), lhsValue, rhsValue, "value")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOldvalue, rhs: rhsOldvalue, with: matcher), lhsOldvalue, rhsOldvalue, "oldValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__event(let lhsEvent), .m_trackEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__event(let lhsEvent), .m_trackScreenEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackScreenEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_trackEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_trackScreenEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_appreview__eventbiValue_biValueaction_actionrating_rating(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_trackEvent__event(p0): return p0.intValue - case let .m_trackEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__event(p0): return p0.intValue - case let .m_trackScreenEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_trackEvent__eventparameters_parameters: return ".trackEvent(_:parameters:)" - case .m_trackEvent__eventbiValue_biValueparameters_parameters: return ".trackEvent(_:biValue:parameters:)" - case .m_trackScreenEvent__eventparameters_parameters: return ".trackScreenEvent(_:parameters:)" - case .m_trackScreenEvent__eventbiValue_biValueparameters_parameters: return ".trackScreenEvent(_:biValue:parameters:)" - case .m_appreview__eventbiValue_biValueaction_actionrating_rating: return ".appreview(_:biValue:action:rating:)" - case .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue: return ".videoQualityChanged(_:bivalue:value:oldValue:)" - case .m_trackEvent__event: return ".trackEvent(_:)" - case .m_trackEvent__eventbiValue_biValue: return ".trackEvent(_:biValue:)" - case .m_trackScreenEvent__event: return ".trackScreenEvent(_:)" - case .m_trackScreenEvent__eventbiValue_biValue: return ".trackScreenEvent(_:biValue:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter) -> Verify { return Verify(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`))} - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter) -> Verify { return Verify(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`))} - public static func trackEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackEvent__event(`event`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`))} - public static func trackScreenEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__event(`event`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String?, Int?) -> Void) -> Perform { - return Perform(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`), performs: perform) - } - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String, String) -> Void) -> Perform { - return Perform(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`), performs: perform) - } - public static func trackEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackEvent__event(`event`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__event(`event`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CorePersistenceProtocol - -open class CorePersistenceProtocolMock: CorePersistenceProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func set(userId: Int) { - addInvocation(.m_set__userId_userId(Parameter.value(`userId`))) - let perform = methodPerformValue(.m_set__userId_userId(Parameter.value(`userId`))) as? (Int) -> Void - perform?(`userId`) - } - - open func getUserID() -> Int? { - addInvocation(.m_getUserID) - let perform = methodPerformValue(.m_getUserID) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getUserID).casted() - } catch { - // do nothing - } - return __value - } - - @MainActor - open func publisher() throws -> AnyPublisher { - addInvocation(.m_publisher) - let perform = methodPerformValue(.m_publisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_publisher).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for publisher(). Use given") - Failure("Stub return value not specified for publisher(). Use given") - } catch { - throw error - } - return __value - } - - open func addToDownloadQueue(tasks: [DownloadDataTask]) { - addInvocation(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) as? ([DownloadDataTask]) -> Void - perform?(`tasks`) - } - - open func saveOfflineProgress(progress: OfflineProgress) { - addInvocation(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) - let perform = methodPerformValue(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) as? (OfflineProgress) -> Void - perform?(`progress`) - } - - open func loadProgress(for blockID: String) -> OfflineProgress? { - addInvocation(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - var __value: OfflineProgress? = nil - do { - __value = try methodReturnValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))).casted() - } catch { - // do nothing - } - return __value - } - - open func loadAllOfflineProgress() -> [OfflineProgress] { - addInvocation(.m_loadAllOfflineProgress) - let perform = methodPerformValue(.m_loadAllOfflineProgress) as? () -> Void - perform?() - var __value: [OfflineProgress] - do { - __value = try methodReturnValue(.m_loadAllOfflineProgress).casted() - } catch { - onFatalFailure("Stub return value not specified for loadAllOfflineProgress(). Use given") - Failure("Stub return value not specified for loadAllOfflineProgress(). Use given") - } - return __value - } - - open func deleteProgress(for blockID: String) { - addInvocation(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - } - - open func deleteAllProgress() { - addInvocation(.m_deleteAllProgress) - let perform = methodPerformValue(.m_deleteAllProgress) as? () -> Void - perform?() - } - - open func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { - addInvocation(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) as? ([CourseBlock], DownloadQuality) -> Void - perform?(`blocks`, `downloadQuality`) - } - - open func updateTask(task: DownloadDataTask) { - addInvocation(.m_updateTask__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_updateTask__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - } - - open func downloadDataTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getDownloadDataTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasks) - let perform = methodPerformValue(.m_getDownloadDataTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasks(). Use given") - Failure("Stub return value not specified for getDownloadDataTasks(). Use given") - } - return __value - } - - open func getDownloadDataTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func deleteDownloadDataTasks(ids: [String]) { - addInvocation(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) - let perform = methodPerformValue(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) as? ([String]) -> Void - perform?(`ids`) - } - - - fileprivate enum MethodType { - case m_set__userId_userId(Parameter) - case m_getUserID - case m_publisher - case m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>) - case m_saveOfflineProgress__progress_progress(Parameter) - case m_loadProgress__for_blockID(Parameter) - case m_loadAllOfflineProgress - case m_deleteProgress__for_blockID(Parameter) - case m_deleteAllProgress - case m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>, Parameter) - case m_updateTask__task_task(Parameter) - case m_downloadDataTask__for_blockId(Parameter) - case m_getDownloadDataTasks - case m_getDownloadDataTasksForCourse__courseId(Parameter) - case m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_set__userId_userId(let lhsUserid), .m_set__userId_userId(let rhsUserid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUserid, rhs: rhsUserid, with: matcher), lhsUserid, rhsUserid, "userId")) - return Matcher.ComparisonResult(results) - - case (.m_getUserID, .m_getUserID): return .match - - case (.m_publisher, .m_publisher): return .match - - case (.m_addToDownloadQueue__tasks_tasks(let lhsTasks), .m_addToDownloadQueue__tasks_tasks(let rhsTasks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTasks, rhs: rhsTasks, with: matcher), lhsTasks, rhsTasks, "tasks")) - return Matcher.ComparisonResult(results) - - case (.m_saveOfflineProgress__progress_progress(let lhsProgress), .m_saveOfflineProgress__progress_progress(let rhsProgress)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsProgress, rhs: rhsProgress, with: matcher), lhsProgress, rhsProgress, "progress")) - return Matcher.ComparisonResult(results) - - case (.m_loadProgress__for_blockID(let lhsBlockid), .m_loadProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_loadAllOfflineProgress, .m_loadAllOfflineProgress): return .match - - case (.m_deleteProgress__for_blockID(let lhsBlockid), .m_deleteProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_deleteAllProgress, .m_deleteAllProgress): return .match - - case (.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let lhsBlocks, let lhsDownloadquality), .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let rhsBlocks, let rhsDownloadquality)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadquality, rhs: rhsDownloadquality, with: matcher), lhsDownloadquality, rhsDownloadquality, "downloadQuality")) - return Matcher.ComparisonResult(results) - - case (.m_updateTask__task_task(let lhsTask), .m_updateTask__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_downloadDataTask__for_blockId(let lhsBlockid), .m_downloadDataTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadDataTasks, .m_getDownloadDataTasks): return .match - - case (.m_getDownloadDataTasksForCourse__courseId(let lhsCourseid), .m_getDownloadDataTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_deleteDownloadDataTasks__ids_ids(let lhsIds), .m_deleteDownloadDataTasks__ids_ids(let rhsIds)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIds, rhs: rhsIds, with: matcher), lhsIds, rhsIds, "ids")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_set__userId_userId(p0): return p0.intValue - case .m_getUserID: return 0 - case .m_publisher: return 0 - case let .m_addToDownloadQueue__tasks_tasks(p0): return p0.intValue - case let .m_saveOfflineProgress__progress_progress(p0): return p0.intValue - case let .m_loadProgress__for_blockID(p0): return p0.intValue - case .m_loadAllOfflineProgress: return 0 - case let .m_deleteProgress__for_blockID(p0): return p0.intValue - case .m_deleteAllProgress: return 0 - case let .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(p0, p1): return p0.intValue + p1.intValue - case let .m_updateTask__task_task(p0): return p0.intValue - case let .m_downloadDataTask__for_blockId(p0): return p0.intValue - case .m_getDownloadDataTasks: return 0 - case let .m_getDownloadDataTasksForCourse__courseId(p0): return p0.intValue - case let .m_deleteDownloadDataTasks__ids_ids(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_set__userId_userId: return ".set(userId:)" - case .m_getUserID: return ".getUserID()" - case .m_publisher: return ".publisher()" - case .m_addToDownloadQueue__tasks_tasks: return ".addToDownloadQueue(tasks:)" - case .m_saveOfflineProgress__progress_progress: return ".saveOfflineProgress(progress:)" - case .m_loadProgress__for_blockID: return ".loadProgress(for:)" - case .m_loadAllOfflineProgress: return ".loadAllOfflineProgress()" - case .m_deleteProgress__for_blockID: return ".deleteProgress(for:)" - case .m_deleteAllProgress: return ".deleteAllProgress()" - case .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality: return ".addToDownloadQueue(blocks:downloadQuality:)" - case .m_updateTask__task_task: return ".updateTask(task:)" - case .m_downloadDataTask__for_blockId: return ".downloadDataTask(for:)" - case .m_getDownloadDataTasks: return ".getDownloadDataTasks()" - case .m_getDownloadDataTasksForCourse__courseId: return ".getDownloadDataTasksForCourse(_:)" - case .m_deleteDownloadDataTasks__ids_ids: return ".deleteDownloadDataTasks(ids:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getUserID(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @MainActor - public static func publisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_publisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadProgress(for blockID: Parameter, willReturn: OfflineProgress?...) -> MethodStub { - return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadAllOfflineProgress(willReturn: [OfflineProgress]...) -> MethodStub { - return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadDataTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getUserID(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func loadProgress(for blockID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [OfflineProgress?] = [] - let given: Given = { return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (OfflineProgress?).self) - willProduce(stubber) - return given - } - public static func loadAllOfflineProgress(willProduce: (Stubber<[OfflineProgress]>) -> Void) -> MethodStub { - let willReturn: [[OfflineProgress]] = [] - let given: Given = { return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([OfflineProgress]).self) - willProduce(stubber) - return given - } - public static func downloadDataTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - @MainActor - public static func publisher(willThrow: Error...) -> MethodStub { - return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) - } - @MainActor - public static func publisher(willProduce: (StubberThrows>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func set(userId: Parameter) -> Verify { return Verify(method: .m_set__userId_userId(`userId`))} - public static func getUserID() -> Verify { return Verify(method: .m_getUserID)} - @MainActor - public static func publisher() -> Verify { return Verify(method: .m_publisher)} - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>) -> Verify { return Verify(method: .m_addToDownloadQueue__tasks_tasks(`tasks`))} - public static func saveOfflineProgress(progress: Parameter) -> Verify { return Verify(method: .m_saveOfflineProgress__progress_progress(`progress`))} - public static func loadProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_loadProgress__for_blockID(`blockID`))} - public static func loadAllOfflineProgress() -> Verify { return Verify(method: .m_loadAllOfflineProgress)} - public static func deleteProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_deleteProgress__for_blockID(`blockID`))} - public static func deleteAllProgress() -> Verify { return Verify(method: .m_deleteAllProgress)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`))} - public static func updateTask(task: Parameter) -> Verify { return Verify(method: .m_updateTask__task_task(`task`))} - public static func downloadDataTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadDataTask__for_blockId(`blockId`))} - public static func getDownloadDataTasks() -> Verify { return Verify(method: .m_getDownloadDataTasks)} - public static func getDownloadDataTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`))} - public static func deleteDownloadDataTasks(ids: Parameter<[String]>) -> Verify { return Verify(method: .m_deleteDownloadDataTasks__ids_ids(`ids`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func set(userId: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_set__userId_userId(`userId`), performs: perform) - } - public static func getUserID(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getUserID, performs: perform) - } - @MainActor - public static func publisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_publisher, performs: perform) - } - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>, perform: @escaping ([DownloadDataTask]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__tasks_tasks(`tasks`), performs: perform) - } - public static func saveOfflineProgress(progress: Parameter, perform: @escaping (OfflineProgress) -> Void) -> Perform { - return Perform(method: .m_saveOfflineProgress__progress_progress(`progress`), performs: perform) - } - public static func loadProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_loadProgress__for_blockID(`blockID`), performs: perform) - } - public static func loadAllOfflineProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_loadAllOfflineProgress, performs: perform) - } - public static func deleteProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_deleteProgress__for_blockID(`blockID`), performs: perform) - } - public static func deleteAllProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAllProgress, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter, perform: @escaping ([CourseBlock], DownloadQuality) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`), performs: perform) - } - public static func updateTask(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_updateTask__task_task(`task`), performs: perform) - } - public static func downloadDataTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadDataTask__for_blockId(`blockId`), performs: perform) - } - public static func getDownloadDataTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasks, performs: perform) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func deleteDownloadDataTasks(ids: Parameter<[String]>, perform: @escaping ([String]) -> Void) -> Perform { - return Perform(method: .m_deleteDownloadDataTasks__ids_ids(`ids`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreStorage - -open class CoreStorageMock: CoreStorage, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var accessToken: String? { - get { invocations.append(.p_accessToken_get); return __p_accessToken ?? optionalGivenGetterValue(.p_accessToken_get, "CoreStorageMock - stub value for accessToken was not defined") } - set { invocations.append(.p_accessToken_set(.value(newValue))); __p_accessToken = newValue } - } - private var __p_accessToken: (String)? - - public var refreshToken: String? { - get { invocations.append(.p_refreshToken_get); return __p_refreshToken ?? optionalGivenGetterValue(.p_refreshToken_get, "CoreStorageMock - stub value for refreshToken was not defined") } - set { invocations.append(.p_refreshToken_set(.value(newValue))); __p_refreshToken = newValue } - } - private var __p_refreshToken: (String)? - - public var pushToken: String? { - get { invocations.append(.p_pushToken_get); return __p_pushToken ?? optionalGivenGetterValue(.p_pushToken_get, "CoreStorageMock - stub value for pushToken was not defined") } - set { invocations.append(.p_pushToken_set(.value(newValue))); __p_pushToken = newValue } - } - private var __p_pushToken: (String)? - - public var appleSignFullName: String? { - get { invocations.append(.p_appleSignFullName_get); return __p_appleSignFullName ?? optionalGivenGetterValue(.p_appleSignFullName_get, "CoreStorageMock - stub value for appleSignFullName was not defined") } - set { invocations.append(.p_appleSignFullName_set(.value(newValue))); __p_appleSignFullName = newValue } - } - private var __p_appleSignFullName: (String)? - - public var appleSignEmail: String? { - get { invocations.append(.p_appleSignEmail_get); return __p_appleSignEmail ?? optionalGivenGetterValue(.p_appleSignEmail_get, "CoreStorageMock - stub value for appleSignEmail was not defined") } - set { invocations.append(.p_appleSignEmail_set(.value(newValue))); __p_appleSignEmail = newValue } - } - private var __p_appleSignEmail: (String)? - - public var cookiesDate: Date? { - get { invocations.append(.p_cookiesDate_get); return __p_cookiesDate ?? optionalGivenGetterValue(.p_cookiesDate_get, "CoreStorageMock - stub value for cookiesDate was not defined") } - set { invocations.append(.p_cookiesDate_set(.value(newValue))); __p_cookiesDate = newValue } - } - private var __p_cookiesDate: (Date)? - - public var reviewLastShownVersion: String? { - get { invocations.append(.p_reviewLastShownVersion_get); return __p_reviewLastShownVersion ?? optionalGivenGetterValue(.p_reviewLastShownVersion_get, "CoreStorageMock - stub value for reviewLastShownVersion was not defined") } - set { invocations.append(.p_reviewLastShownVersion_set(.value(newValue))); __p_reviewLastShownVersion = newValue } - } - private var __p_reviewLastShownVersion: (String)? - - public var lastReviewDate: Date? { - get { invocations.append(.p_lastReviewDate_get); return __p_lastReviewDate ?? optionalGivenGetterValue(.p_lastReviewDate_get, "CoreStorageMock - stub value for lastReviewDate was not defined") } - set { invocations.append(.p_lastReviewDate_set(.value(newValue))); __p_lastReviewDate = newValue } - } - private var __p_lastReviewDate: (Date)? - - public var user: DataLayer.User? { - get { invocations.append(.p_user_get); return __p_user ?? optionalGivenGetterValue(.p_user_get, "CoreStorageMock - stub value for user was not defined") } - set { invocations.append(.p_user_set(.value(newValue))); __p_user = newValue } - } - private var __p_user: (DataLayer.User)? - - public var userSettings: UserSettings? { - get { invocations.append(.p_userSettings_get); return __p_userSettings ?? optionalGivenGetterValue(.p_userSettings_get, "CoreStorageMock - stub value for userSettings was not defined") } - set { invocations.append(.p_userSettings_set(.value(newValue))); __p_userSettings = newValue } - } - private var __p_userSettings: (UserSettings)? - - public var resetAppSupportDirectoryUserData: Bool? { - get { invocations.append(.p_resetAppSupportDirectoryUserData_get); return __p_resetAppSupportDirectoryUserData ?? optionalGivenGetterValue(.p_resetAppSupportDirectoryUserData_get, "CoreStorageMock - stub value for resetAppSupportDirectoryUserData was not defined") } - set { invocations.append(.p_resetAppSupportDirectoryUserData_set(.value(newValue))); __p_resetAppSupportDirectoryUserData = newValue } - } - private var __p_resetAppSupportDirectoryUserData: (Bool)? - - public var useRelativeDates: Bool { - get { invocations.append(.p_useRelativeDates_get); return __p_useRelativeDates ?? givenGetterValue(.p_useRelativeDates_get, "CoreStorageMock - stub value for useRelativeDates was not defined") } - set { invocations.append(.p_useRelativeDates_set(.value(newValue))); __p_useRelativeDates = newValue } - } - private var __p_useRelativeDates: (Bool)? - - public var lastUsedSocialAuth: String? { - get { invocations.append(.p_lastUsedSocialAuth_get); return __p_lastUsedSocialAuth ?? optionalGivenGetterValue(.p_lastUsedSocialAuth_get, "CoreStorageMock - stub value for lastUsedSocialAuth was not defined") } - set { invocations.append(.p_lastUsedSocialAuth_set(.value(newValue))); __p_lastUsedSocialAuth = newValue } - } - private var __p_lastUsedSocialAuth: (String)? - - public var latestAvailableAppVersion: String? { - get { invocations.append(.p_latestAvailableAppVersion_get); return __p_latestAvailableAppVersion ?? optionalGivenGetterValue(.p_latestAvailableAppVersion_get, "CoreStorageMock - stub value for latestAvailableAppVersion was not defined") } - set { invocations.append(.p_latestAvailableAppVersion_set(.value(newValue))); __p_latestAvailableAppVersion = newValue } - } - private var __p_latestAvailableAppVersion: (String)? - - public var updateAppRequired: Bool { - get { invocations.append(.p_updateAppRequired_get); return __p_updateAppRequired ?? givenGetterValue(.p_updateAppRequired_get, "CoreStorageMock - stub value for updateAppRequired was not defined") } - set { invocations.append(.p_updateAppRequired_set(.value(newValue))); __p_updateAppRequired = newValue } - } - private var __p_updateAppRequired: (Bool)? - - - - - - open func clear() { - addInvocation(.m_clear) - let perform = methodPerformValue(.m_clear) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_clear - case p_accessToken_get - case p_accessToken_set(Parameter) - case p_refreshToken_get - case p_refreshToken_set(Parameter) - case p_pushToken_get - case p_pushToken_set(Parameter) - case p_appleSignFullName_get - case p_appleSignFullName_set(Parameter) - case p_appleSignEmail_get - case p_appleSignEmail_set(Parameter) - case p_cookiesDate_get - case p_cookiesDate_set(Parameter) - case p_reviewLastShownVersion_get - case p_reviewLastShownVersion_set(Parameter) - case p_lastReviewDate_get - case p_lastReviewDate_set(Parameter) - case p_user_get - case p_user_set(Parameter) - case p_userSettings_get - case p_userSettings_set(Parameter) - case p_resetAppSupportDirectoryUserData_get - case p_resetAppSupportDirectoryUserData_set(Parameter) - case p_useRelativeDates_get - case p_useRelativeDates_set(Parameter) - case p_lastUsedSocialAuth_get - case p_lastUsedSocialAuth_set(Parameter) - case p_latestAvailableAppVersion_get - case p_latestAvailableAppVersion_set(Parameter) - case p_updateAppRequired_get - case p_updateAppRequired_set(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_clear, .m_clear): return .match - case (.p_accessToken_get,.p_accessToken_get): return Matcher.ComparisonResult.match - case (.p_accessToken_set(let left),.p_accessToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_refreshToken_get,.p_refreshToken_get): return Matcher.ComparisonResult.match - case (.p_refreshToken_set(let left),.p_refreshToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_pushToken_get,.p_pushToken_get): return Matcher.ComparisonResult.match - case (.p_pushToken_set(let left),.p_pushToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignFullName_get,.p_appleSignFullName_get): return Matcher.ComparisonResult.match - case (.p_appleSignFullName_set(let left),.p_appleSignFullName_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignEmail_get,.p_appleSignEmail_get): return Matcher.ComparisonResult.match - case (.p_appleSignEmail_set(let left),.p_appleSignEmail_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_cookiesDate_get,.p_cookiesDate_get): return Matcher.ComparisonResult.match - case (.p_cookiesDate_set(let left),.p_cookiesDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_reviewLastShownVersion_get,.p_reviewLastShownVersion_get): return Matcher.ComparisonResult.match - case (.p_reviewLastShownVersion_set(let left),.p_reviewLastShownVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastReviewDate_get,.p_lastReviewDate_get): return Matcher.ComparisonResult.match - case (.p_lastReviewDate_set(let left),.p_lastReviewDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_user_get,.p_user_get): return Matcher.ComparisonResult.match - case (.p_user_set(let left),.p_user_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_userSettings_get,.p_userSettings_get): return Matcher.ComparisonResult.match - case (.p_userSettings_set(let left),.p_userSettings_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_resetAppSupportDirectoryUserData_get,.p_resetAppSupportDirectoryUserData_get): return Matcher.ComparisonResult.match - case (.p_resetAppSupportDirectoryUserData_set(let left),.p_resetAppSupportDirectoryUserData_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_useRelativeDates_get,.p_useRelativeDates_get): return Matcher.ComparisonResult.match - case (.p_useRelativeDates_set(let left),.p_useRelativeDates_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastUsedSocialAuth_get,.p_lastUsedSocialAuth_get): return Matcher.ComparisonResult.match - case (.p_lastUsedSocialAuth_set(let left),.p_lastUsedSocialAuth_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_latestAvailableAppVersion_get,.p_latestAvailableAppVersion_get): return Matcher.ComparisonResult.match - case (.p_latestAvailableAppVersion_set(let left),.p_latestAvailableAppVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_updateAppRequired_get,.p_updateAppRequired_get): return Matcher.ComparisonResult.match - case (.p_updateAppRequired_set(let left),.p_updateAppRequired_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_clear: return 0 - case .p_accessToken_get: return 0 - case .p_accessToken_set(let newValue): return newValue.intValue - case .p_refreshToken_get: return 0 - case .p_refreshToken_set(let newValue): return newValue.intValue - case .p_pushToken_get: return 0 - case .p_pushToken_set(let newValue): return newValue.intValue - case .p_appleSignFullName_get: return 0 - case .p_appleSignFullName_set(let newValue): return newValue.intValue - case .p_appleSignEmail_get: return 0 - case .p_appleSignEmail_set(let newValue): return newValue.intValue - case .p_cookiesDate_get: return 0 - case .p_cookiesDate_set(let newValue): return newValue.intValue - case .p_reviewLastShownVersion_get: return 0 - case .p_reviewLastShownVersion_set(let newValue): return newValue.intValue - case .p_lastReviewDate_get: return 0 - case .p_lastReviewDate_set(let newValue): return newValue.intValue - case .p_user_get: return 0 - case .p_user_set(let newValue): return newValue.intValue - case .p_userSettings_get: return 0 - case .p_userSettings_set(let newValue): return newValue.intValue - case .p_resetAppSupportDirectoryUserData_get: return 0 - case .p_resetAppSupportDirectoryUserData_set(let newValue): return newValue.intValue - case .p_useRelativeDates_get: return 0 - case .p_useRelativeDates_set(let newValue): return newValue.intValue - case .p_lastUsedSocialAuth_get: return 0 - case .p_lastUsedSocialAuth_set(let newValue): return newValue.intValue - case .p_latestAvailableAppVersion_get: return 0 - case .p_latestAvailableAppVersion_set(let newValue): return newValue.intValue - case .p_updateAppRequired_get: return 0 - case .p_updateAppRequired_set(let newValue): return newValue.intValue - } - } - func assertionName() -> String { - switch self { - case .m_clear: return ".clear()" - case .p_accessToken_get: return "[get] .accessToken" - case .p_accessToken_set: return "[set] .accessToken" - case .p_refreshToken_get: return "[get] .refreshToken" - case .p_refreshToken_set: return "[set] .refreshToken" - case .p_pushToken_get: return "[get] .pushToken" - case .p_pushToken_set: return "[set] .pushToken" - case .p_appleSignFullName_get: return "[get] .appleSignFullName" - case .p_appleSignFullName_set: return "[set] .appleSignFullName" - case .p_appleSignEmail_get: return "[get] .appleSignEmail" - case .p_appleSignEmail_set: return "[set] .appleSignEmail" - case .p_cookiesDate_get: return "[get] .cookiesDate" - case .p_cookiesDate_set: return "[set] .cookiesDate" - case .p_reviewLastShownVersion_get: return "[get] .reviewLastShownVersion" - case .p_reviewLastShownVersion_set: return "[set] .reviewLastShownVersion" - case .p_lastReviewDate_get: return "[get] .lastReviewDate" - case .p_lastReviewDate_set: return "[set] .lastReviewDate" - case .p_user_get: return "[get] .user" - case .p_user_set: return "[set] .user" - case .p_userSettings_get: return "[get] .userSettings" - case .p_userSettings_set: return "[set] .userSettings" - case .p_resetAppSupportDirectoryUserData_get: return "[get] .resetAppSupportDirectoryUserData" - case .p_resetAppSupportDirectoryUserData_set: return "[set] .resetAppSupportDirectoryUserData" - case .p_useRelativeDates_get: return "[get] .useRelativeDates" - case .p_useRelativeDates_set: return "[set] .useRelativeDates" - case .p_lastUsedSocialAuth_get: return "[get] .lastUsedSocialAuth" - case .p_lastUsedSocialAuth_set: return "[set] .lastUsedSocialAuth" - case .p_latestAvailableAppVersion_get: return "[get] .latestAvailableAppVersion" - case .p_latestAvailableAppVersion_set: return "[set] .latestAvailableAppVersion" - case .p_updateAppRequired_get: return "[get] .updateAppRequired" - case .p_updateAppRequired_set: return "[set] .updateAppRequired" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func accessToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_accessToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func refreshToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_refreshToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func pushToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_pushToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignFullName(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignFullName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignEmail(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func cookiesDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_cookiesDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func reviewLastShownVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_reviewLastShownVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastReviewDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_lastReviewDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func user(getter defaultValue: DataLayer.User?...) -> PropertyStub { - return Given(method: .p_user_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func userSettings(getter defaultValue: UserSettings?...) -> PropertyStub { - return Given(method: .p_userSettings_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func resetAppSupportDirectoryUserData(getter defaultValue: Bool?...) -> PropertyStub { - return Given(method: .p_resetAppSupportDirectoryUserData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func useRelativeDates(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_useRelativeDates_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastUsedSocialAuth(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_lastUsedSocialAuth_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func latestAvailableAppVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_latestAvailableAppVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func updateAppRequired(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_updateAppRequired_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func clear() -> Verify { return Verify(method: .m_clear)} - public static var accessToken: Verify { return Verify(method: .p_accessToken_get) } - public static func accessToken(set newValue: Parameter) -> Verify { return Verify(method: .p_accessToken_set(newValue)) } - public static var refreshToken: Verify { return Verify(method: .p_refreshToken_get) } - public static func refreshToken(set newValue: Parameter) -> Verify { return Verify(method: .p_refreshToken_set(newValue)) } - public static var pushToken: Verify { return Verify(method: .p_pushToken_get) } - public static func pushToken(set newValue: Parameter) -> Verify { return Verify(method: .p_pushToken_set(newValue)) } - public static var appleSignFullName: Verify { return Verify(method: .p_appleSignFullName_get) } - public static func appleSignFullName(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignFullName_set(newValue)) } - public static var appleSignEmail: Verify { return Verify(method: .p_appleSignEmail_get) } - public static func appleSignEmail(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignEmail_set(newValue)) } - public static var cookiesDate: Verify { return Verify(method: .p_cookiesDate_get) } - public static func cookiesDate(set newValue: Parameter) -> Verify { return Verify(method: .p_cookiesDate_set(newValue)) } - public static var reviewLastShownVersion: Verify { return Verify(method: .p_reviewLastShownVersion_get) } - public static func reviewLastShownVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_reviewLastShownVersion_set(newValue)) } - public static var lastReviewDate: Verify { return Verify(method: .p_lastReviewDate_get) } - public static func lastReviewDate(set newValue: Parameter) -> Verify { return Verify(method: .p_lastReviewDate_set(newValue)) } - public static var user: Verify { return Verify(method: .p_user_get) } - public static func user(set newValue: Parameter) -> Verify { return Verify(method: .p_user_set(newValue)) } - public static var userSettings: Verify { return Verify(method: .p_userSettings_get) } - public static func userSettings(set newValue: Parameter) -> Verify { return Verify(method: .p_userSettings_set(newValue)) } - public static var resetAppSupportDirectoryUserData: Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_get) } - public static func resetAppSupportDirectoryUserData(set newValue: Parameter) -> Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_set(newValue)) } - public static var useRelativeDates: Verify { return Verify(method: .p_useRelativeDates_get) } - public static func useRelativeDates(set newValue: Parameter) -> Verify { return Verify(method: .p_useRelativeDates_set(newValue)) } - public static var lastUsedSocialAuth: Verify { return Verify(method: .p_lastUsedSocialAuth_get) } - public static func lastUsedSocialAuth(set newValue: Parameter) -> Verify { return Verify(method: .p_lastUsedSocialAuth_set(newValue)) } - public static var latestAvailableAppVersion: Verify { return Verify(method: .p_latestAvailableAppVersion_get) } - public static func latestAvailableAppVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_latestAvailableAppVersion_set(newValue)) } - public static var updateAppRequired: Verify { return Verify(method: .p_updateAppRequired_get) } - public static func updateAppRequired(set newValue: Parameter) -> Verify { return Verify(method: .p_updateAppRequired_set(newValue)) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func clear(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_clear, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CourseAnalytics - -open class CourseAnalyticsMock: CourseAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func resumeCourseClicked(courseId: String, courseName: String, blockId: String) { - addInvocation(.m_resumeCourseClicked__courseId_courseIdcourseName_courseNameblockId_blockId(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_resumeCourseClicked__courseId_courseIdcourseName_courseNameblockId_blockId(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`))) as? (String, String, String) -> Void - perform?(`courseId`, `courseName`, `blockId`) - } - - open func sequentialClicked(courseId: String, courseName: String, blockId: String, blockName: String) { - addInvocation(.m_sequentialClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) - let perform = methodPerformValue(.m_sequentialClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `blockId`, `blockName`) - } - - open func verticalClicked(courseId: String, courseName: String, blockId: String, blockName: String) { - addInvocation(.m_verticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) - let perform = methodPerformValue(.m_verticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `blockId`, `blockName`) - } - - open func nextBlockClicked(courseId: String, courseName: String, blockId: String, blockName: String) { - addInvocation(.m_nextBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) - let perform = methodPerformValue(.m_nextBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `blockId`, `blockName`) - } - - open func prevBlockClicked(courseId: String, courseName: String, blockId: String, blockName: String) { - addInvocation(.m_prevBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) - let perform = methodPerformValue(.m_prevBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `blockId`, `blockName`) - } - - open func finishVerticalClicked(courseId: String, courseName: String, blockId: String, blockName: String) { - addInvocation(.m_finishVerticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) - let perform = methodPerformValue(.m_finishVerticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `blockId`, `blockName`) - } - - open func finishVerticalNextSectionClicked(courseId: String, courseName: String, blockId: String, blockName: String) { - addInvocation(.m_finishVerticalNextSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) - let perform = methodPerformValue(.m_finishVerticalNextSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `blockId`, `blockName`) - } - - open func finishVerticalBackToOutlineClicked(courseId: String, courseName: String) { - addInvocation(.m_finishVerticalBackToOutlineClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_finishVerticalBackToOutlineClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseOutlineCourseTabClicked(courseId: String, courseName: String) { - addInvocation(.m_courseOutlineCourseTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseOutlineCourseTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseOutlineContentTabClicked(courseId: String, courseName: String) { - addInvocation(.m_courseOutlineContentTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseOutlineContentTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseOutlineProgressTabClicked(courseId: String, courseName: String) { - addInvocation(.m_courseOutlineProgressTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseOutlineProgressTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseOutlineVideosTabClicked(courseId: String, courseName: String) { - addInvocation(.m_courseOutlineVideosTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseOutlineVideosTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseOutlineOfflineTabClicked(courseId: String, courseName: String) { - addInvocation(.m_courseOutlineOfflineTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseOutlineOfflineTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseOutlineDatesTabClicked(courseId: String, courseName: String) { - addInvocation(.m_courseOutlineDatesTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseOutlineDatesTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseOutlineDiscussionTabClicked(courseId: String, courseName: String) { - addInvocation(.m_courseOutlineDiscussionTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseOutlineDiscussionTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseOutlineHandoutsTabClicked(courseId: String, courseName: String) { - addInvocation(.m_courseOutlineHandoutsTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseOutlineHandoutsTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseOutlineAssignmentsTabClicked(courseId: String, courseName: String) { - addInvocation(.m_courseOutlineAssignmentsTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseOutlineAssignmentsTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseContentAllTabClicked(courseId: String, courseName: String) { - addInvocation(.m_courseContentAllTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseContentAllTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseContentVideosTabClicked(courseId: String, courseName: String) { - addInvocation(.m_courseContentVideosTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseContentVideosTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseContentAssignmentsTabClicked(courseId: String, courseName: String) { - addInvocation(.m_courseContentAssignmentsTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseContentAssignmentsTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseVideoClicked(courseId: String, courseName: String, blockId: String, blockName: String) { - addInvocation(.m_courseVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) - let perform = methodPerformValue(.m_courseVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `blockId`, `blockName`) - } - - open func courseAssignmentClicked(courseId: String, courseName: String, blockId: String, blockName: String) { - addInvocation(.m_courseAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) - let perform = methodPerformValue(.m_courseAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `blockId`, `blockName`) - } - - open func contentPageSectionClicked(courseId: String, courseName: String, blockId: String, blockName: String) { - addInvocation(.m_contentPageSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) - let perform = methodPerformValue(.m_contentPageSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `blockId`, `blockName`) - } - - open func contentPageShowCompletedSubsectionClicked(courseId: String, courseName: String) { - addInvocation(.m_contentPageShowCompletedSubsectionClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_contentPageShowCompletedSubsectionClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func progressTabClicked(courseId: String, courseName: String) { - addInvocation(.m_progressTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_progressTabClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseHomeViewAllContentClicked(courseId: String, courseName: String) { - addInvocation(.m_courseHomeViewAllContentClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseHomeViewAllContentClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseHomeVideoClicked(courseId: String, courseName: String, blockId: String, blockName: String) { - addInvocation(.m_courseHomeVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) - let perform = methodPerformValue(.m_courseHomeVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `blockId`, `blockName`) - } - - open func courseHomeViewAllVideosClicked(courseId: String, courseName: String) { - addInvocation(.m_courseHomeViewAllVideosClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseHomeViewAllVideosClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseHomeAssignmentClicked(courseId: String, courseName: String, blockId: String, blockName: String) { - addInvocation(.m_courseHomeAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) - let perform = methodPerformValue(.m_courseHomeAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`blockId`), Parameter.value(`blockName`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `blockId`, `blockName`) - } - - open func courseHomeViewAllAssignmentsClicked(courseId: String, courseName: String) { - addInvocation(.m_courseHomeViewAllAssignmentsClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseHomeViewAllAssignmentsClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseHomeGradesViewProgressClicked(courseId: String, courseName: String) { - addInvocation(.m_courseHomeGradesViewProgressClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseHomeGradesViewProgressClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseHomeSectionSubsectionClick(courseId: String, courseName: String, courseSection: String, courseSubsection: String) { - addInvocation(.m_courseHomeSectionSubsectionClick__courseId_courseIdcourseName_courseNamecourseSection_courseSectioncourseSubsection_courseSubsection(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`courseSection`), Parameter.value(`courseSubsection`))) - let perform = methodPerformValue(.m_courseHomeSectionSubsectionClick__courseId_courseIdcourseName_courseNamecourseSection_courseSectioncourseSubsection_courseSubsection(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`courseSection`), Parameter.value(`courseSubsection`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `courseSection`, `courseSubsection`) - } - - open func datesComponentTapped(courseId: String, blockId: String, link: String, supported: Bool) { - addInvocation(.m_datesComponentTapped__courseId_courseIdblockId_blockIdlink_linksupported_supported(Parameter.value(`courseId`), Parameter.value(`blockId`), Parameter.value(`link`), Parameter.value(`supported`))) - let perform = methodPerformValue(.m_datesComponentTapped__courseId_courseIdblockId_blockIdlink_linksupported_supported(Parameter.value(`courseId`), Parameter.value(`blockId`), Parameter.value(`link`), Parameter.value(`supported`))) as? (String, String, String, Bool) -> Void - perform?(`courseId`, `blockId`, `link`, `supported`) - } - - open func calendarSyncToggle(enrollmentMode: EnrollmentMode, pacing: CoursePacing, courseId: String, action: CalendarDialogueAction) { - addInvocation(.m_calendarSyncToggle__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdaction_action(Parameter.value(`enrollmentMode`), Parameter.value(`pacing`), Parameter.value(`courseId`), Parameter.value(`action`))) - let perform = methodPerformValue(.m_calendarSyncToggle__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdaction_action(Parameter.value(`enrollmentMode`), Parameter.value(`pacing`), Parameter.value(`courseId`), Parameter.value(`action`))) as? (EnrollmentMode, CoursePacing, String, CalendarDialogueAction) -> Void - perform?(`enrollmentMode`, `pacing`, `courseId`, `action`) - } - - open func calendarSyncDialogAction(enrollmentMode: EnrollmentMode, pacing: CoursePacing, courseId: String, dialog: CalendarDialogueType, action: CalendarDialogueAction) { - addInvocation(.m_calendarSyncDialogAction__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIddialog_dialogaction_action(Parameter.value(`enrollmentMode`), Parameter.value(`pacing`), Parameter.value(`courseId`), Parameter.value(`dialog`), Parameter.value(`action`))) - let perform = methodPerformValue(.m_calendarSyncDialogAction__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIddialog_dialogaction_action(Parameter.value(`enrollmentMode`), Parameter.value(`pacing`), Parameter.value(`courseId`), Parameter.value(`dialog`), Parameter.value(`action`))) as? (EnrollmentMode, CoursePacing, String, CalendarDialogueType, CalendarDialogueAction) -> Void - perform?(`enrollmentMode`, `pacing`, `courseId`, `dialog`, `action`) - } - - open func calendarSyncSnackbar(enrollmentMode: EnrollmentMode, pacing: CoursePacing, courseId: String, snackbar: SnackbarType) { - addInvocation(.m_calendarSyncSnackbar__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdsnackbar_snackbar(Parameter.value(`enrollmentMode`), Parameter.value(`pacing`), Parameter.value(`courseId`), Parameter.value(`snackbar`))) - let perform = methodPerformValue(.m_calendarSyncSnackbar__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdsnackbar_snackbar(Parameter.value(`enrollmentMode`), Parameter.value(`pacing`), Parameter.value(`courseId`), Parameter.value(`snackbar`))) as? (EnrollmentMode, CoursePacing, String, SnackbarType) -> Void - perform?(`enrollmentMode`, `pacing`, `courseId`, `snackbar`) - } - - open func trackCourseEvent(_ event: AnalyticsEvent, biValue: EventBIValue, courseID: String) { - addInvocation(.m_trackCourseEvent__eventbiValue_biValuecourseID_courseID(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_trackCourseEvent__eventbiValue_biValuecourseID_courseID(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`courseID`))) as? (AnalyticsEvent, EventBIValue, String) -> Void - perform?(`event`, `biValue`, `courseID`) - } - - open func trackCourseScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, courseID: String) { - addInvocation(.m_trackCourseScreenEvent__eventbiValue_biValuecourseID_courseID(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_trackCourseScreenEvent__eventbiValue_biValuecourseID_courseID(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`courseID`))) as? (AnalyticsEvent, EventBIValue, String) -> Void - perform?(`event`, `biValue`, `courseID`) - } - - open func plsEvent(_ event: AnalyticsEvent, bivalue: EventBIValue, courseID: String, screenName: String, type: String) { - addInvocation(.m_plsEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_type(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`courseID`), Parameter.value(`screenName`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_plsEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_type(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`courseID`), Parameter.value(`screenName`), Parameter.value(`type`))) as? (AnalyticsEvent, EventBIValue, String, String, String) -> Void - perform?(`event`, `bivalue`, `courseID`, `screenName`, `type`) - } - - open func plsSuccessEvent(_ event: AnalyticsEvent, bivalue: EventBIValue, courseID: String, screenName: String, type: String, success: Bool) { - addInvocation(.m_plsSuccessEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_typesuccess_success(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`courseID`), Parameter.value(`screenName`), Parameter.value(`type`), Parameter.value(`success`))) - let perform = methodPerformValue(.m_plsSuccessEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_typesuccess_success(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`courseID`), Parameter.value(`screenName`), Parameter.value(`type`), Parameter.value(`success`))) as? (AnalyticsEvent, EventBIValue, String, String, String, Bool) -> Void - perform?(`event`, `bivalue`, `courseID`, `screenName`, `type`, `success`) - } - - open func bulkDownloadVideosToggle(courseID: String, action: Bool) { - addInvocation(.m_bulkDownloadVideosToggle__courseID_courseIDaction_action(Parameter.value(`courseID`), Parameter.value(`action`))) - let perform = methodPerformValue(.m_bulkDownloadVideosToggle__courseID_courseIDaction_action(Parameter.value(`courseID`), Parameter.value(`action`))) as? (String, Bool) -> Void - perform?(`courseID`, `action`) - } - - open func bulkDownloadVideosSubsection(courseID: String, sectionID: String, subSectionID: String, videos: Int) { - addInvocation(.m_bulkDownloadVideosSubsection__courseID_courseIDsectionID_sectionIDsubSectionID_subSectionIDvideos_videos(Parameter.value(`courseID`), Parameter.value(`sectionID`), Parameter.value(`subSectionID`), Parameter.value(`videos`))) - let perform = methodPerformValue(.m_bulkDownloadVideosSubsection__courseID_courseIDsectionID_sectionIDsubSectionID_subSectionIDvideos_videos(Parameter.value(`courseID`), Parameter.value(`sectionID`), Parameter.value(`subSectionID`), Parameter.value(`videos`))) as? (String, String, String, Int) -> Void - perform?(`courseID`, `sectionID`, `subSectionID`, `videos`) - } - - open func bulkDeleteVideosSubsection(courseID: String, subSectionID: String, videos: Int) { - addInvocation(.m_bulkDeleteVideosSubsection__courseID_courseIDsubSectionID_subSectionIDvideos_videos(Parameter.value(`courseID`), Parameter.value(`subSectionID`), Parameter.value(`videos`))) - let perform = methodPerformValue(.m_bulkDeleteVideosSubsection__courseID_courseIDsubSectionID_subSectionIDvideos_videos(Parameter.value(`courseID`), Parameter.value(`subSectionID`), Parameter.value(`videos`))) as? (String, String, Int) -> Void - perform?(`courseID`, `subSectionID`, `videos`) - } - - open func bulkDownloadVideosSection(courseID: String, sectionID: String, videos: Int) { - addInvocation(.m_bulkDownloadVideosSection__courseID_courseIDsectionID_sectionIDvideos_videos(Parameter.value(`courseID`), Parameter.value(`sectionID`), Parameter.value(`videos`))) - let perform = methodPerformValue(.m_bulkDownloadVideosSection__courseID_courseIDsectionID_sectionIDvideos_videos(Parameter.value(`courseID`), Parameter.value(`sectionID`), Parameter.value(`videos`))) as? (String, String, Int) -> Void - perform?(`courseID`, `sectionID`, `videos`) - } - - open func bulkDeleteVideosSection(courseID: String, sectionId: String, videos: Int) { - addInvocation(.m_bulkDeleteVideosSection__courseID_courseIDsectionId_sectionIdvideos_videos(Parameter.value(`courseID`), Parameter.value(`sectionId`), Parameter.value(`videos`))) - let perform = methodPerformValue(.m_bulkDeleteVideosSection__courseID_courseIDsectionId_sectionIdvideos_videos(Parameter.value(`courseID`), Parameter.value(`sectionId`), Parameter.value(`videos`))) as? (String, String, Int) -> Void - perform?(`courseID`, `sectionId`, `videos`) - } - - open func videoLoaded(courseID: String, blockID: String, videoURL: String) { - addInvocation(.m_videoLoaded__courseID_courseIDblockID_blockIDvideoURL_videoURL(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`videoURL`))) - let perform = methodPerformValue(.m_videoLoaded__courseID_courseIDblockID_blockIDvideoURL_videoURL(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`videoURL`))) as? (String, String, String) -> Void - perform?(`courseID`, `blockID`, `videoURL`) - } - - open func videoPlayed(courseID: String, blockID: String, videoURL: String) { - addInvocation(.m_videoPlayed__courseID_courseIDblockID_blockIDvideoURL_videoURL(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`videoURL`))) - let perform = methodPerformValue(.m_videoPlayed__courseID_courseIDblockID_blockIDvideoURL_videoURL(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`videoURL`))) as? (String, String, String) -> Void - perform?(`courseID`, `blockID`, `videoURL`) - } - - open func videoSpeedChange(courseID: String, blockID: String, videoURL: String, oldSpeed: Float, newSpeed: Float, currentTime: Double, duration: Double) { - addInvocation(.m_videoSpeedChange__courseID_courseIDblockID_blockIDvideoURL_videoURLoldSpeed_oldSpeednewSpeed_newSpeedcurrentTime_currentTimeduration_duration(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`videoURL`), Parameter.value(`oldSpeed`), Parameter.value(`newSpeed`), Parameter.value(`currentTime`), Parameter.value(`duration`))) - let perform = methodPerformValue(.m_videoSpeedChange__courseID_courseIDblockID_blockIDvideoURL_videoURLoldSpeed_oldSpeednewSpeed_newSpeedcurrentTime_currentTimeduration_duration(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`videoURL`), Parameter.value(`oldSpeed`), Parameter.value(`newSpeed`), Parameter.value(`currentTime`), Parameter.value(`duration`))) as? (String, String, String, Float, Float, Double, Double) -> Void - perform?(`courseID`, `blockID`, `videoURL`, `oldSpeed`, `newSpeed`, `currentTime`, `duration`) - } - - open func videoPaused(courseID: String, blockID: String, videoURL: String, currentTime: Double, duration: Double) { - addInvocation(.m_videoPaused__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`videoURL`), Parameter.value(`currentTime`), Parameter.value(`duration`))) - let perform = methodPerformValue(.m_videoPaused__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`videoURL`), Parameter.value(`currentTime`), Parameter.value(`duration`))) as? (String, String, String, Double, Double) -> Void - perform?(`courseID`, `blockID`, `videoURL`, `currentTime`, `duration`) - } - - open func videoCompleted(courseID: String, blockID: String, videoURL: String, currentTime: Double, duration: Double) { - addInvocation(.m_videoCompleted__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`videoURL`), Parameter.value(`currentTime`), Parameter.value(`duration`))) - let perform = methodPerformValue(.m_videoCompleted__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`videoURL`), Parameter.value(`currentTime`), Parameter.value(`duration`))) as? (String, String, String, Double, Double) -> Void - perform?(`courseID`, `blockID`, `videoURL`, `currentTime`, `duration`) - } - - - fileprivate enum MethodType { - case m_resumeCourseClicked__courseId_courseIdcourseName_courseNameblockId_blockId(Parameter, Parameter, Parameter) - case m_sequentialClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter, Parameter, Parameter, Parameter) - case m_verticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter, Parameter, Parameter, Parameter) - case m_nextBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter, Parameter, Parameter, Parameter) - case m_prevBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter, Parameter, Parameter, Parameter) - case m_finishVerticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter, Parameter, Parameter, Parameter) - case m_finishVerticalNextSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter, Parameter, Parameter, Parameter) - case m_finishVerticalBackToOutlineClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseOutlineCourseTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseOutlineContentTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseOutlineProgressTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseOutlineVideosTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseOutlineOfflineTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseOutlineDatesTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseOutlineDiscussionTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseOutlineHandoutsTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseOutlineAssignmentsTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseContentAllTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseContentVideosTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseContentAssignmentsTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter, Parameter, Parameter, Parameter) - case m_courseAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter, Parameter, Parameter, Parameter) - case m_contentPageSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter, Parameter, Parameter, Parameter) - case m_contentPageShowCompletedSubsectionClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_progressTabClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseHomeViewAllContentClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseHomeVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter, Parameter, Parameter, Parameter) - case m_courseHomeViewAllVideosClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseHomeAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(Parameter, Parameter, Parameter, Parameter) - case m_courseHomeViewAllAssignmentsClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseHomeGradesViewProgressClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseHomeSectionSubsectionClick__courseId_courseIdcourseName_courseNamecourseSection_courseSectioncourseSubsection_courseSubsection(Parameter, Parameter, Parameter, Parameter) - case m_datesComponentTapped__courseId_courseIdblockId_blockIdlink_linksupported_supported(Parameter, Parameter, Parameter, Parameter) - case m_calendarSyncToggle__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdaction_action(Parameter, Parameter, Parameter, Parameter) - case m_calendarSyncDialogAction__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIddialog_dialogaction_action(Parameter, Parameter, Parameter, Parameter, Parameter) - case m_calendarSyncSnackbar__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdsnackbar_snackbar(Parameter, Parameter, Parameter, Parameter) - case m_trackCourseEvent__eventbiValue_biValuecourseID_courseID(Parameter, Parameter, Parameter) - case m_trackCourseScreenEvent__eventbiValue_biValuecourseID_courseID(Parameter, Parameter, Parameter) - case m_plsEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_type(Parameter, Parameter, Parameter, Parameter, Parameter) - case m_plsSuccessEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_typesuccess_success(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter) - case m_bulkDownloadVideosToggle__courseID_courseIDaction_action(Parameter, Parameter) - case m_bulkDownloadVideosSubsection__courseID_courseIDsectionID_sectionIDsubSectionID_subSectionIDvideos_videos(Parameter, Parameter, Parameter, Parameter) - case m_bulkDeleteVideosSubsection__courseID_courseIDsubSectionID_subSectionIDvideos_videos(Parameter, Parameter, Parameter) - case m_bulkDownloadVideosSection__courseID_courseIDsectionID_sectionIDvideos_videos(Parameter, Parameter, Parameter) - case m_bulkDeleteVideosSection__courseID_courseIDsectionId_sectionIdvideos_videos(Parameter, Parameter, Parameter) - case m_videoLoaded__courseID_courseIDblockID_blockIDvideoURL_videoURL(Parameter, Parameter, Parameter) - case m_videoPlayed__courseID_courseIDblockID_blockIDvideoURL_videoURL(Parameter, Parameter, Parameter) - case m_videoSpeedChange__courseID_courseIDblockID_blockIDvideoURL_videoURLoldSpeed_oldSpeednewSpeed_newSpeedcurrentTime_currentTimeduration_duration(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter) - case m_videoPaused__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(Parameter, Parameter, Parameter, Parameter, Parameter) - case m_videoCompleted__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(Parameter, Parameter, Parameter, Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_resumeCourseClicked__courseId_courseIdcourseName_courseNameblockId_blockId(let lhsCourseid, let lhsCoursename, let lhsBlockid), .m_resumeCourseClicked__courseId_courseIdcourseName_courseNameblockId_blockId(let rhsCourseid, let rhsCoursename, let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - return Matcher.ComparisonResult(results) - - case (.m_sequentialClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let lhsCourseid, let lhsCoursename, let lhsBlockid, let lhsBlockname), .m_sequentialClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let rhsCourseid, let rhsCoursename, let rhsBlockid, let rhsBlockname)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockname, rhs: rhsBlockname, with: matcher), lhsBlockname, rhsBlockname, "blockName")) - return Matcher.ComparisonResult(results) - - case (.m_verticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let lhsCourseid, let lhsCoursename, let lhsBlockid, let lhsBlockname), .m_verticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let rhsCourseid, let rhsCoursename, let rhsBlockid, let rhsBlockname)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockname, rhs: rhsBlockname, with: matcher), lhsBlockname, rhsBlockname, "blockName")) - return Matcher.ComparisonResult(results) - - case (.m_nextBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let lhsCourseid, let lhsCoursename, let lhsBlockid, let lhsBlockname), .m_nextBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let rhsCourseid, let rhsCoursename, let rhsBlockid, let rhsBlockname)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockname, rhs: rhsBlockname, with: matcher), lhsBlockname, rhsBlockname, "blockName")) - return Matcher.ComparisonResult(results) - - case (.m_prevBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let lhsCourseid, let lhsCoursename, let lhsBlockid, let lhsBlockname), .m_prevBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let rhsCourseid, let rhsCoursename, let rhsBlockid, let rhsBlockname)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockname, rhs: rhsBlockname, with: matcher), lhsBlockname, rhsBlockname, "blockName")) - return Matcher.ComparisonResult(results) - - case (.m_finishVerticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let lhsCourseid, let lhsCoursename, let lhsBlockid, let lhsBlockname), .m_finishVerticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let rhsCourseid, let rhsCoursename, let rhsBlockid, let rhsBlockname)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockname, rhs: rhsBlockname, with: matcher), lhsBlockname, rhsBlockname, "blockName")) - return Matcher.ComparisonResult(results) - - case (.m_finishVerticalNextSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let lhsCourseid, let lhsCoursename, let lhsBlockid, let lhsBlockname), .m_finishVerticalNextSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let rhsCourseid, let rhsCoursename, let rhsBlockid, let rhsBlockname)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockname, rhs: rhsBlockname, with: matcher), lhsBlockname, rhsBlockname, "blockName")) - return Matcher.ComparisonResult(results) - - case (.m_finishVerticalBackToOutlineClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_finishVerticalBackToOutlineClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseOutlineCourseTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseOutlineCourseTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseOutlineContentTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseOutlineContentTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseOutlineProgressTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseOutlineProgressTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseOutlineVideosTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseOutlineVideosTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseOutlineOfflineTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseOutlineOfflineTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseOutlineDatesTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseOutlineDatesTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseOutlineDiscussionTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseOutlineDiscussionTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseOutlineHandoutsTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseOutlineHandoutsTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseOutlineAssignmentsTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseOutlineAssignmentsTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseContentAllTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseContentAllTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseContentVideosTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseContentVideosTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseContentAssignmentsTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseContentAssignmentsTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let lhsCourseid, let lhsCoursename, let lhsBlockid, let lhsBlockname), .m_courseVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let rhsCourseid, let rhsCoursename, let rhsBlockid, let rhsBlockname)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockname, rhs: rhsBlockname, with: matcher), lhsBlockname, rhsBlockname, "blockName")) - return Matcher.ComparisonResult(results) - - case (.m_courseAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let lhsCourseid, let lhsCoursename, let lhsBlockid, let lhsBlockname), .m_courseAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let rhsCourseid, let rhsCoursename, let rhsBlockid, let rhsBlockname)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockname, rhs: rhsBlockname, with: matcher), lhsBlockname, rhsBlockname, "blockName")) - return Matcher.ComparisonResult(results) - - case (.m_contentPageSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let lhsCourseid, let lhsCoursename, let lhsBlockid, let lhsBlockname), .m_contentPageSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let rhsCourseid, let rhsCoursename, let rhsBlockid, let rhsBlockname)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockname, rhs: rhsBlockname, with: matcher), lhsBlockname, rhsBlockname, "blockName")) - return Matcher.ComparisonResult(results) - - case (.m_contentPageShowCompletedSubsectionClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_contentPageShowCompletedSubsectionClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_progressTabClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_progressTabClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseHomeViewAllContentClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseHomeViewAllContentClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseHomeVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let lhsCourseid, let lhsCoursename, let lhsBlockid, let lhsBlockname), .m_courseHomeVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let rhsCourseid, let rhsCoursename, let rhsBlockid, let rhsBlockname)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockname, rhs: rhsBlockname, with: matcher), lhsBlockname, rhsBlockname, "blockName")) - return Matcher.ComparisonResult(results) - - case (.m_courseHomeViewAllVideosClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseHomeViewAllVideosClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseHomeAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let lhsCourseid, let lhsCoursename, let lhsBlockid, let lhsBlockname), .m_courseHomeAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(let rhsCourseid, let rhsCoursename, let rhsBlockid, let rhsBlockname)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockname, rhs: rhsBlockname, with: matcher), lhsBlockname, rhsBlockname, "blockName")) - return Matcher.ComparisonResult(results) - - case (.m_courseHomeViewAllAssignmentsClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseHomeViewAllAssignmentsClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseHomeGradesViewProgressClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseHomeGradesViewProgressClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseHomeSectionSubsectionClick__courseId_courseIdcourseName_courseNamecourseSection_courseSectioncourseSubsection_courseSubsection(let lhsCourseid, let lhsCoursename, let lhsCoursesection, let lhsCoursesubsection), .m_courseHomeSectionSubsectionClick__courseId_courseIdcourseName_courseNamecourseSection_courseSectioncourseSubsection_courseSubsection(let rhsCourseid, let rhsCoursename, let rhsCoursesection, let rhsCoursesubsection)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursesection, rhs: rhsCoursesection, with: matcher), lhsCoursesection, rhsCoursesection, "courseSection")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursesubsection, rhs: rhsCoursesubsection, with: matcher), lhsCoursesubsection, rhsCoursesubsection, "courseSubsection")) - return Matcher.ComparisonResult(results) - - case (.m_datesComponentTapped__courseId_courseIdblockId_blockIdlink_linksupported_supported(let lhsCourseid, let lhsBlockid, let lhsLink, let lhsSupported), .m_datesComponentTapped__courseId_courseIdblockId_blockIdlink_linksupported_supported(let rhsCourseid, let rhsBlockid, let rhsLink, let rhsSupported)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsLink, rhs: rhsLink, with: matcher), lhsLink, rhsLink, "link")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSupported, rhs: rhsSupported, with: matcher), lhsSupported, rhsSupported, "supported")) - return Matcher.ComparisonResult(results) - - case (.m_calendarSyncToggle__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdaction_action(let lhsEnrollmentmode, let lhsPacing, let lhsCourseid, let lhsAction), .m_calendarSyncToggle__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdaction_action(let rhsEnrollmentmode, let rhsPacing, let rhsCourseid, let rhsAction)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEnrollmentmode, rhs: rhsEnrollmentmode, with: matcher), lhsEnrollmentmode, rhsEnrollmentmode, "enrollmentMode")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPacing, rhs: rhsPacing, with: matcher), lhsPacing, rhsPacing, "pacing")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - return Matcher.ComparisonResult(results) - - case (.m_calendarSyncDialogAction__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIddialog_dialogaction_action(let lhsEnrollmentmode, let lhsPacing, let lhsCourseid, let lhsDialog, let lhsAction), .m_calendarSyncDialogAction__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIddialog_dialogaction_action(let rhsEnrollmentmode, let rhsPacing, let rhsCourseid, let rhsDialog, let rhsAction)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEnrollmentmode, rhs: rhsEnrollmentmode, with: matcher), lhsEnrollmentmode, rhsEnrollmentmode, "enrollmentMode")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPacing, rhs: rhsPacing, with: matcher), lhsPacing, rhsPacing, "pacing")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDialog, rhs: rhsDialog, with: matcher), lhsDialog, rhsDialog, "dialog")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - return Matcher.ComparisonResult(results) - - case (.m_calendarSyncSnackbar__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdsnackbar_snackbar(let lhsEnrollmentmode, let lhsPacing, let lhsCourseid, let lhsSnackbar), .m_calendarSyncSnackbar__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdsnackbar_snackbar(let rhsEnrollmentmode, let rhsPacing, let rhsCourseid, let rhsSnackbar)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEnrollmentmode, rhs: rhsEnrollmentmode, with: matcher), lhsEnrollmentmode, rhsEnrollmentmode, "enrollmentMode")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPacing, rhs: rhsPacing, with: matcher), lhsPacing, rhsPacing, "pacing")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSnackbar, rhs: rhsSnackbar, with: matcher), lhsSnackbar, rhsSnackbar, "snackbar")) - return Matcher.ComparisonResult(results) - - case (.m_trackCourseEvent__eventbiValue_biValuecourseID_courseID(let lhsEvent, let lhsBivalue, let lhsCourseid), .m_trackCourseEvent__eventbiValue_biValuecourseID_courseID(let rhsEvent, let rhsBivalue, let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_trackCourseScreenEvent__eventbiValue_biValuecourseID_courseID(let lhsEvent, let lhsBivalue, let lhsCourseid), .m_trackCourseScreenEvent__eventbiValue_biValuecourseID_courseID(let rhsEvent, let rhsBivalue, let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_plsEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_type(let lhsEvent, let lhsBivalue, let lhsCourseid, let lhsScreenname, let lhsType), .m_plsEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_type(let rhsEvent, let rhsBivalue, let rhsCourseid, let rhsScreenname, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "bivalue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsScreenname, rhs: rhsScreenname, with: matcher), lhsScreenname, rhsScreenname, "screenName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_plsSuccessEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_typesuccess_success(let lhsEvent, let lhsBivalue, let lhsCourseid, let lhsScreenname, let lhsType, let lhsSuccess), .m_plsSuccessEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_typesuccess_success(let rhsEvent, let rhsBivalue, let rhsCourseid, let rhsScreenname, let rhsType, let rhsSuccess)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "bivalue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsScreenname, rhs: rhsScreenname, with: matcher), lhsScreenname, rhsScreenname, "screenName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSuccess, rhs: rhsSuccess, with: matcher), lhsSuccess, rhsSuccess, "success")) - return Matcher.ComparisonResult(results) - - case (.m_bulkDownloadVideosToggle__courseID_courseIDaction_action(let lhsCourseid, let lhsAction), .m_bulkDownloadVideosToggle__courseID_courseIDaction_action(let rhsCourseid, let rhsAction)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - return Matcher.ComparisonResult(results) - - case (.m_bulkDownloadVideosSubsection__courseID_courseIDsectionID_sectionIDsubSectionID_subSectionIDvideos_videos(let lhsCourseid, let lhsSectionid, let lhsSubsectionid, let lhsVideos), .m_bulkDownloadVideosSubsection__courseID_courseIDsectionID_sectionIDsubSectionID_subSectionIDvideos_videos(let rhsCourseid, let rhsSectionid, let rhsSubsectionid, let rhsVideos)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSectionid, rhs: rhsSectionid, with: matcher), lhsSectionid, rhsSectionid, "sectionID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSubsectionid, rhs: rhsSubsectionid, with: matcher), lhsSubsectionid, rhsSubsectionid, "subSectionID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsVideos, rhs: rhsVideos, with: matcher), lhsVideos, rhsVideos, "videos")) - return Matcher.ComparisonResult(results) - - case (.m_bulkDeleteVideosSubsection__courseID_courseIDsubSectionID_subSectionIDvideos_videos(let lhsCourseid, let lhsSubsectionid, let lhsVideos), .m_bulkDeleteVideosSubsection__courseID_courseIDsubSectionID_subSectionIDvideos_videos(let rhsCourseid, let rhsSubsectionid, let rhsVideos)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSubsectionid, rhs: rhsSubsectionid, with: matcher), lhsSubsectionid, rhsSubsectionid, "subSectionID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsVideos, rhs: rhsVideos, with: matcher), lhsVideos, rhsVideos, "videos")) - return Matcher.ComparisonResult(results) - - case (.m_bulkDownloadVideosSection__courseID_courseIDsectionID_sectionIDvideos_videos(let lhsCourseid, let lhsSectionid, let lhsVideos), .m_bulkDownloadVideosSection__courseID_courseIDsectionID_sectionIDvideos_videos(let rhsCourseid, let rhsSectionid, let rhsVideos)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSectionid, rhs: rhsSectionid, with: matcher), lhsSectionid, rhsSectionid, "sectionID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsVideos, rhs: rhsVideos, with: matcher), lhsVideos, rhsVideos, "videos")) - return Matcher.ComparisonResult(results) - - case (.m_bulkDeleteVideosSection__courseID_courseIDsectionId_sectionIdvideos_videos(let lhsCourseid, let lhsSectionid, let lhsVideos), .m_bulkDeleteVideosSection__courseID_courseIDsectionId_sectionIdvideos_videos(let rhsCourseid, let rhsSectionid, let rhsVideos)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSectionid, rhs: rhsSectionid, with: matcher), lhsSectionid, rhsSectionid, "sectionId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsVideos, rhs: rhsVideos, with: matcher), lhsVideos, rhsVideos, "videos")) - return Matcher.ComparisonResult(results) - - case (.m_videoLoaded__courseID_courseIDblockID_blockIDvideoURL_videoURL(let lhsCourseid, let lhsBlockid, let lhsVideourl), .m_videoLoaded__courseID_courseIDblockID_blockIDvideoURL_videoURL(let rhsCourseid, let rhsBlockid, let rhsVideourl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsVideourl, rhs: rhsVideourl, with: matcher), lhsVideourl, rhsVideourl, "videoURL")) - return Matcher.ComparisonResult(results) - - case (.m_videoPlayed__courseID_courseIDblockID_blockIDvideoURL_videoURL(let lhsCourseid, let lhsBlockid, let lhsVideourl), .m_videoPlayed__courseID_courseIDblockID_blockIDvideoURL_videoURL(let rhsCourseid, let rhsBlockid, let rhsVideourl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsVideourl, rhs: rhsVideourl, with: matcher), lhsVideourl, rhsVideourl, "videoURL")) - return Matcher.ComparisonResult(results) - - case (.m_videoSpeedChange__courseID_courseIDblockID_blockIDvideoURL_videoURLoldSpeed_oldSpeednewSpeed_newSpeedcurrentTime_currentTimeduration_duration(let lhsCourseid, let lhsBlockid, let lhsVideourl, let lhsOldspeed, let lhsNewspeed, let lhsCurrenttime, let lhsDuration), .m_videoSpeedChange__courseID_courseIDblockID_blockIDvideoURL_videoURLoldSpeed_oldSpeednewSpeed_newSpeedcurrentTime_currentTimeduration_duration(let rhsCourseid, let rhsBlockid, let rhsVideourl, let rhsOldspeed, let rhsNewspeed, let rhsCurrenttime, let rhsDuration)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsVideourl, rhs: rhsVideourl, with: matcher), lhsVideourl, rhsVideourl, "videoURL")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOldspeed, rhs: rhsOldspeed, with: matcher), lhsOldspeed, rhsOldspeed, "oldSpeed")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNewspeed, rhs: rhsNewspeed, with: matcher), lhsNewspeed, rhsNewspeed, "newSpeed")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCurrenttime, rhs: rhsCurrenttime, with: matcher), lhsCurrenttime, rhsCurrenttime, "currentTime")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDuration, rhs: rhsDuration, with: matcher), lhsDuration, rhsDuration, "duration")) - return Matcher.ComparisonResult(results) - - case (.m_videoPaused__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(let lhsCourseid, let lhsBlockid, let lhsVideourl, let lhsCurrenttime, let lhsDuration), .m_videoPaused__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(let rhsCourseid, let rhsBlockid, let rhsVideourl, let rhsCurrenttime, let rhsDuration)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsVideourl, rhs: rhsVideourl, with: matcher), lhsVideourl, rhsVideourl, "videoURL")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCurrenttime, rhs: rhsCurrenttime, with: matcher), lhsCurrenttime, rhsCurrenttime, "currentTime")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDuration, rhs: rhsDuration, with: matcher), lhsDuration, rhsDuration, "duration")) - return Matcher.ComparisonResult(results) - - case (.m_videoCompleted__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(let lhsCourseid, let lhsBlockid, let lhsVideourl, let lhsCurrenttime, let lhsDuration), .m_videoCompleted__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(let rhsCourseid, let rhsBlockid, let rhsVideourl, let rhsCurrenttime, let rhsDuration)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsVideourl, rhs: rhsVideourl, with: matcher), lhsVideourl, rhsVideourl, "videoURL")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCurrenttime, rhs: rhsCurrenttime, with: matcher), lhsCurrenttime, rhsCurrenttime, "currentTime")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDuration, rhs: rhsDuration, with: matcher), lhsDuration, rhsDuration, "duration")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_resumeCourseClicked__courseId_courseIdcourseName_courseNameblockId_blockId(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_sequentialClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_verticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_nextBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_prevBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_finishVerticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_finishVerticalNextSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_finishVerticalBackToOutlineClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseOutlineCourseTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseOutlineContentTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseOutlineProgressTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseOutlineVideosTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseOutlineOfflineTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseOutlineDatesTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseOutlineDiscussionTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseOutlineHandoutsTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseOutlineAssignmentsTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseContentAllTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseContentVideosTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseContentAssignmentsTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_courseAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_contentPageSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_contentPageShowCompletedSubsectionClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_progressTabClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseHomeViewAllContentClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseHomeVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_courseHomeViewAllVideosClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseHomeAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_courseHomeViewAllAssignmentsClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseHomeGradesViewProgressClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseHomeSectionSubsectionClick__courseId_courseIdcourseName_courseNamecourseSection_courseSectioncourseSubsection_courseSubsection(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_datesComponentTapped__courseId_courseIdblockId_blockIdlink_linksupported_supported(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_calendarSyncToggle__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdaction_action(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_calendarSyncDialogAction__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIddialog_dialogaction_action(p0, p1, p2, p3, p4): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue - case let .m_calendarSyncSnackbar__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdsnackbar_snackbar(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_trackCourseEvent__eventbiValue_biValuecourseID_courseID(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_trackCourseScreenEvent__eventbiValue_biValuecourseID_courseID(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_plsEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_type(p0, p1, p2, p3, p4): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue - case let .m_plsSuccessEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_typesuccess_success(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_bulkDownloadVideosToggle__courseID_courseIDaction_action(p0, p1): return p0.intValue + p1.intValue - case let .m_bulkDownloadVideosSubsection__courseID_courseIDsectionID_sectionIDsubSectionID_subSectionIDvideos_videos(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_bulkDeleteVideosSubsection__courseID_courseIDsubSectionID_subSectionIDvideos_videos(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_bulkDownloadVideosSection__courseID_courseIDsectionID_sectionIDvideos_videos(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_bulkDeleteVideosSection__courseID_courseIDsectionId_sectionIdvideos_videos(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_videoLoaded__courseID_courseIDblockID_blockIDvideoURL_videoURL(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_videoPlayed__courseID_courseIDblockID_blockIDvideoURL_videoURL(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_videoSpeedChange__courseID_courseIDblockID_blockIDvideoURL_videoURLoldSpeed_oldSpeednewSpeed_newSpeedcurrentTime_currentTimeduration_duration(p0, p1, p2, p3, p4, p5, p6): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue - case let .m_videoPaused__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(p0, p1, p2, p3, p4): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue - case let .m_videoCompleted__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(p0, p1, p2, p3, p4): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue - } - } - func assertionName() -> String { - switch self { - case .m_resumeCourseClicked__courseId_courseIdcourseName_courseNameblockId_blockId: return ".resumeCourseClicked(courseId:courseName:blockId:)" - case .m_sequentialClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName: return ".sequentialClicked(courseId:courseName:blockId:blockName:)" - case .m_verticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName: return ".verticalClicked(courseId:courseName:blockId:blockName:)" - case .m_nextBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName: return ".nextBlockClicked(courseId:courseName:blockId:blockName:)" - case .m_prevBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName: return ".prevBlockClicked(courseId:courseName:blockId:blockName:)" - case .m_finishVerticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName: return ".finishVerticalClicked(courseId:courseName:blockId:blockName:)" - case .m_finishVerticalNextSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName: return ".finishVerticalNextSectionClicked(courseId:courseName:blockId:blockName:)" - case .m_finishVerticalBackToOutlineClicked__courseId_courseIdcourseName_courseName: return ".finishVerticalBackToOutlineClicked(courseId:courseName:)" - case .m_courseOutlineCourseTabClicked__courseId_courseIdcourseName_courseName: return ".courseOutlineCourseTabClicked(courseId:courseName:)" - case .m_courseOutlineContentTabClicked__courseId_courseIdcourseName_courseName: return ".courseOutlineContentTabClicked(courseId:courseName:)" - case .m_courseOutlineProgressTabClicked__courseId_courseIdcourseName_courseName: return ".courseOutlineProgressTabClicked(courseId:courseName:)" - case .m_courseOutlineVideosTabClicked__courseId_courseIdcourseName_courseName: return ".courseOutlineVideosTabClicked(courseId:courseName:)" - case .m_courseOutlineOfflineTabClicked__courseId_courseIdcourseName_courseName: return ".courseOutlineOfflineTabClicked(courseId:courseName:)" - case .m_courseOutlineDatesTabClicked__courseId_courseIdcourseName_courseName: return ".courseOutlineDatesTabClicked(courseId:courseName:)" - case .m_courseOutlineDiscussionTabClicked__courseId_courseIdcourseName_courseName: return ".courseOutlineDiscussionTabClicked(courseId:courseName:)" - case .m_courseOutlineHandoutsTabClicked__courseId_courseIdcourseName_courseName: return ".courseOutlineHandoutsTabClicked(courseId:courseName:)" - case .m_courseOutlineAssignmentsTabClicked__courseId_courseIdcourseName_courseName: return ".courseOutlineAssignmentsTabClicked(courseId:courseName:)" - case .m_courseContentAllTabClicked__courseId_courseIdcourseName_courseName: return ".courseContentAllTabClicked(courseId:courseName:)" - case .m_courseContentVideosTabClicked__courseId_courseIdcourseName_courseName: return ".courseContentVideosTabClicked(courseId:courseName:)" - case .m_courseContentAssignmentsTabClicked__courseId_courseIdcourseName_courseName: return ".courseContentAssignmentsTabClicked(courseId:courseName:)" - case .m_courseVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName: return ".courseVideoClicked(courseId:courseName:blockId:blockName:)" - case .m_courseAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName: return ".courseAssignmentClicked(courseId:courseName:blockId:blockName:)" - case .m_contentPageSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName: return ".contentPageSectionClicked(courseId:courseName:blockId:blockName:)" - case .m_contentPageShowCompletedSubsectionClicked__courseId_courseIdcourseName_courseName: return ".contentPageShowCompletedSubsectionClicked(courseId:courseName:)" - case .m_progressTabClicked__courseId_courseIdcourseName_courseName: return ".progressTabClicked(courseId:courseName:)" - case .m_courseHomeViewAllContentClicked__courseId_courseIdcourseName_courseName: return ".courseHomeViewAllContentClicked(courseId:courseName:)" - case .m_courseHomeVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName: return ".courseHomeVideoClicked(courseId:courseName:blockId:blockName:)" - case .m_courseHomeViewAllVideosClicked__courseId_courseIdcourseName_courseName: return ".courseHomeViewAllVideosClicked(courseId:courseName:)" - case .m_courseHomeAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName: return ".courseHomeAssignmentClicked(courseId:courseName:blockId:blockName:)" - case .m_courseHomeViewAllAssignmentsClicked__courseId_courseIdcourseName_courseName: return ".courseHomeViewAllAssignmentsClicked(courseId:courseName:)" - case .m_courseHomeGradesViewProgressClicked__courseId_courseIdcourseName_courseName: return ".courseHomeGradesViewProgressClicked(courseId:courseName:)" - case .m_courseHomeSectionSubsectionClick__courseId_courseIdcourseName_courseNamecourseSection_courseSectioncourseSubsection_courseSubsection: return ".courseHomeSectionSubsectionClick(courseId:courseName:courseSection:courseSubsection:)" - case .m_datesComponentTapped__courseId_courseIdblockId_blockIdlink_linksupported_supported: return ".datesComponentTapped(courseId:blockId:link:supported:)" - case .m_calendarSyncToggle__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdaction_action: return ".calendarSyncToggle(enrollmentMode:pacing:courseId:action:)" - case .m_calendarSyncDialogAction__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIddialog_dialogaction_action: return ".calendarSyncDialogAction(enrollmentMode:pacing:courseId:dialog:action:)" - case .m_calendarSyncSnackbar__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdsnackbar_snackbar: return ".calendarSyncSnackbar(enrollmentMode:pacing:courseId:snackbar:)" - case .m_trackCourseEvent__eventbiValue_biValuecourseID_courseID: return ".trackCourseEvent(_:biValue:courseID:)" - case .m_trackCourseScreenEvent__eventbiValue_biValuecourseID_courseID: return ".trackCourseScreenEvent(_:biValue:courseID:)" - case .m_plsEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_type: return ".plsEvent(_:bivalue:courseID:screenName:type:)" - case .m_plsSuccessEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_typesuccess_success: return ".plsSuccessEvent(_:bivalue:courseID:screenName:type:success:)" - case .m_bulkDownloadVideosToggle__courseID_courseIDaction_action: return ".bulkDownloadVideosToggle(courseID:action:)" - case .m_bulkDownloadVideosSubsection__courseID_courseIDsectionID_sectionIDsubSectionID_subSectionIDvideos_videos: return ".bulkDownloadVideosSubsection(courseID:sectionID:subSectionID:videos:)" - case .m_bulkDeleteVideosSubsection__courseID_courseIDsubSectionID_subSectionIDvideos_videos: return ".bulkDeleteVideosSubsection(courseID:subSectionID:videos:)" - case .m_bulkDownloadVideosSection__courseID_courseIDsectionID_sectionIDvideos_videos: return ".bulkDownloadVideosSection(courseID:sectionID:videos:)" - case .m_bulkDeleteVideosSection__courseID_courseIDsectionId_sectionIdvideos_videos: return ".bulkDeleteVideosSection(courseID:sectionId:videos:)" - case .m_videoLoaded__courseID_courseIDblockID_blockIDvideoURL_videoURL: return ".videoLoaded(courseID:blockID:videoURL:)" - case .m_videoPlayed__courseID_courseIDblockID_blockIDvideoURL_videoURL: return ".videoPlayed(courseID:blockID:videoURL:)" - case .m_videoSpeedChange__courseID_courseIDblockID_blockIDvideoURL_videoURLoldSpeed_oldSpeednewSpeed_newSpeedcurrentTime_currentTimeduration_duration: return ".videoSpeedChange(courseID:blockID:videoURL:oldSpeed:newSpeed:currentTime:duration:)" - case .m_videoPaused__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration: return ".videoPaused(courseID:blockID:videoURL:currentTime:duration:)" - case .m_videoCompleted__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration: return ".videoCompleted(courseID:blockID:videoURL:currentTime:duration:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func resumeCourseClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter) -> Verify { return Verify(method: .m_resumeCourseClicked__courseId_courseIdcourseName_courseNameblockId_blockId(`courseId`, `courseName`, `blockId`))} - public static func sequentialClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter) -> Verify { return Verify(method: .m_sequentialClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`))} - public static func verticalClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter) -> Verify { return Verify(method: .m_verticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`))} - public static func nextBlockClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter) -> Verify { return Verify(method: .m_nextBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`))} - public static func prevBlockClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter) -> Verify { return Verify(method: .m_prevBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`))} - public static func finishVerticalClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter) -> Verify { return Verify(method: .m_finishVerticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`))} - public static func finishVerticalNextSectionClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter) -> Verify { return Verify(method: .m_finishVerticalNextSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`))} - public static func finishVerticalBackToOutlineClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_finishVerticalBackToOutlineClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseOutlineCourseTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseOutlineCourseTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseOutlineContentTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseOutlineContentTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseOutlineProgressTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseOutlineProgressTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseOutlineVideosTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseOutlineVideosTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseOutlineOfflineTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseOutlineOfflineTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseOutlineDatesTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseOutlineDatesTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseOutlineDiscussionTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseOutlineDiscussionTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseOutlineHandoutsTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseOutlineHandoutsTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseOutlineAssignmentsTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseOutlineAssignmentsTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseContentAllTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseContentAllTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseContentVideosTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseContentVideosTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseContentAssignmentsTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseContentAssignmentsTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseVideoClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter) -> Verify { return Verify(method: .m_courseVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`))} - public static func courseAssignmentClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter) -> Verify { return Verify(method: .m_courseAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`))} - public static func contentPageSectionClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter) -> Verify { return Verify(method: .m_contentPageSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`))} - public static func contentPageShowCompletedSubsectionClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_contentPageShowCompletedSubsectionClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func progressTabClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_progressTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseHomeViewAllContentClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseHomeViewAllContentClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseHomeVideoClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter) -> Verify { return Verify(method: .m_courseHomeVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`))} - public static func courseHomeViewAllVideosClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseHomeViewAllVideosClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseHomeAssignmentClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter) -> Verify { return Verify(method: .m_courseHomeAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`))} - public static func courseHomeViewAllAssignmentsClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseHomeViewAllAssignmentsClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseHomeGradesViewProgressClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseHomeGradesViewProgressClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseHomeSectionSubsectionClick(courseId: Parameter, courseName: Parameter, courseSection: Parameter, courseSubsection: Parameter) -> Verify { return Verify(method: .m_courseHomeSectionSubsectionClick__courseId_courseIdcourseName_courseNamecourseSection_courseSectioncourseSubsection_courseSubsection(`courseId`, `courseName`, `courseSection`, `courseSubsection`))} - public static func datesComponentTapped(courseId: Parameter, blockId: Parameter, link: Parameter, supported: Parameter) -> Verify { return Verify(method: .m_datesComponentTapped__courseId_courseIdblockId_blockIdlink_linksupported_supported(`courseId`, `blockId`, `link`, `supported`))} - public static func calendarSyncToggle(enrollmentMode: Parameter, pacing: Parameter, courseId: Parameter, action: Parameter) -> Verify { return Verify(method: .m_calendarSyncToggle__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdaction_action(`enrollmentMode`, `pacing`, `courseId`, `action`))} - public static func calendarSyncDialogAction(enrollmentMode: Parameter, pacing: Parameter, courseId: Parameter, dialog: Parameter, action: Parameter) -> Verify { return Verify(method: .m_calendarSyncDialogAction__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIddialog_dialogaction_action(`enrollmentMode`, `pacing`, `courseId`, `dialog`, `action`))} - public static func calendarSyncSnackbar(enrollmentMode: Parameter, pacing: Parameter, courseId: Parameter, snackbar: Parameter) -> Verify { return Verify(method: .m_calendarSyncSnackbar__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdsnackbar_snackbar(`enrollmentMode`, `pacing`, `courseId`, `snackbar`))} - public static func trackCourseEvent(_ event: Parameter, biValue: Parameter, courseID: Parameter) -> Verify { return Verify(method: .m_trackCourseEvent__eventbiValue_biValuecourseID_courseID(`event`, `biValue`, `courseID`))} - public static func trackCourseScreenEvent(_ event: Parameter, biValue: Parameter, courseID: Parameter) -> Verify { return Verify(method: .m_trackCourseScreenEvent__eventbiValue_biValuecourseID_courseID(`event`, `biValue`, `courseID`))} - public static func plsEvent(_ event: Parameter, bivalue: Parameter, courseID: Parameter, screenName: Parameter, type: Parameter) -> Verify { return Verify(method: .m_plsEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_type(`event`, `bivalue`, `courseID`, `screenName`, `type`))} - public static func plsSuccessEvent(_ event: Parameter, bivalue: Parameter, courseID: Parameter, screenName: Parameter, type: Parameter, success: Parameter) -> Verify { return Verify(method: .m_plsSuccessEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_typesuccess_success(`event`, `bivalue`, `courseID`, `screenName`, `type`, `success`))} - public static func bulkDownloadVideosToggle(courseID: Parameter, action: Parameter) -> Verify { return Verify(method: .m_bulkDownloadVideosToggle__courseID_courseIDaction_action(`courseID`, `action`))} - public static func bulkDownloadVideosSubsection(courseID: Parameter, sectionID: Parameter, subSectionID: Parameter, videos: Parameter) -> Verify { return Verify(method: .m_bulkDownloadVideosSubsection__courseID_courseIDsectionID_sectionIDsubSectionID_subSectionIDvideos_videos(`courseID`, `sectionID`, `subSectionID`, `videos`))} - public static func bulkDeleteVideosSubsection(courseID: Parameter, subSectionID: Parameter, videos: Parameter) -> Verify { return Verify(method: .m_bulkDeleteVideosSubsection__courseID_courseIDsubSectionID_subSectionIDvideos_videos(`courseID`, `subSectionID`, `videos`))} - public static func bulkDownloadVideosSection(courseID: Parameter, sectionID: Parameter, videos: Parameter) -> Verify { return Verify(method: .m_bulkDownloadVideosSection__courseID_courseIDsectionID_sectionIDvideos_videos(`courseID`, `sectionID`, `videos`))} - public static func bulkDeleteVideosSection(courseID: Parameter, sectionId: Parameter, videos: Parameter) -> Verify { return Verify(method: .m_bulkDeleteVideosSection__courseID_courseIDsectionId_sectionIdvideos_videos(`courseID`, `sectionId`, `videos`))} - public static func videoLoaded(courseID: Parameter, blockID: Parameter, videoURL: Parameter) -> Verify { return Verify(method: .m_videoLoaded__courseID_courseIDblockID_blockIDvideoURL_videoURL(`courseID`, `blockID`, `videoURL`))} - public static func videoPlayed(courseID: Parameter, blockID: Parameter, videoURL: Parameter) -> Verify { return Verify(method: .m_videoPlayed__courseID_courseIDblockID_blockIDvideoURL_videoURL(`courseID`, `blockID`, `videoURL`))} - public static func videoSpeedChange(courseID: Parameter, blockID: Parameter, videoURL: Parameter, oldSpeed: Parameter, newSpeed: Parameter, currentTime: Parameter, duration: Parameter) -> Verify { return Verify(method: .m_videoSpeedChange__courseID_courseIDblockID_blockIDvideoURL_videoURLoldSpeed_oldSpeednewSpeed_newSpeedcurrentTime_currentTimeduration_duration(`courseID`, `blockID`, `videoURL`, `oldSpeed`, `newSpeed`, `currentTime`, `duration`))} - public static func videoPaused(courseID: Parameter, blockID: Parameter, videoURL: Parameter, currentTime: Parameter, duration: Parameter) -> Verify { return Verify(method: .m_videoPaused__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(`courseID`, `blockID`, `videoURL`, `currentTime`, `duration`))} - public static func videoCompleted(courseID: Parameter, blockID: Parameter, videoURL: Parameter, currentTime: Parameter, duration: Parameter) -> Verify { return Verify(method: .m_videoCompleted__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(`courseID`, `blockID`, `videoURL`, `currentTime`, `duration`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func resumeCourseClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_resumeCourseClicked__courseId_courseIdcourseName_courseNameblockId_blockId(`courseId`, `courseName`, `blockId`), performs: perform) - } - public static func sequentialClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_sequentialClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`), performs: perform) - } - public static func verticalClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_verticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`), performs: perform) - } - public static func nextBlockClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_nextBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`), performs: perform) - } - public static func prevBlockClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_prevBlockClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`), performs: perform) - } - public static func finishVerticalClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_finishVerticalClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`), performs: perform) - } - public static func finishVerticalNextSectionClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_finishVerticalNextSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`), performs: perform) - } - public static func finishVerticalBackToOutlineClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_finishVerticalBackToOutlineClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseOutlineCourseTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseOutlineCourseTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseOutlineContentTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseOutlineContentTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseOutlineProgressTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseOutlineProgressTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseOutlineVideosTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseOutlineVideosTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseOutlineOfflineTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseOutlineOfflineTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseOutlineDatesTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseOutlineDatesTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseOutlineDiscussionTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseOutlineDiscussionTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseOutlineHandoutsTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseOutlineHandoutsTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseOutlineAssignmentsTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseOutlineAssignmentsTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseContentAllTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseContentAllTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseContentVideosTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseContentVideosTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseContentAssignmentsTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseContentAssignmentsTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseVideoClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_courseVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`), performs: perform) - } - public static func courseAssignmentClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_courseAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`), performs: perform) - } - public static func contentPageSectionClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_contentPageSectionClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`), performs: perform) - } - public static func contentPageShowCompletedSubsectionClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_contentPageShowCompletedSubsectionClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func progressTabClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_progressTabClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseHomeViewAllContentClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseHomeViewAllContentClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseHomeVideoClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_courseHomeVideoClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`), performs: perform) - } - public static func courseHomeViewAllVideosClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseHomeViewAllVideosClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseHomeAssignmentClicked(courseId: Parameter, courseName: Parameter, blockId: Parameter, blockName: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_courseHomeAssignmentClicked__courseId_courseIdcourseName_courseNameblockId_blockIdblockName_blockName(`courseId`, `courseName`, `blockId`, `blockName`), performs: perform) - } - public static func courseHomeViewAllAssignmentsClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseHomeViewAllAssignmentsClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseHomeGradesViewProgressClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseHomeGradesViewProgressClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseHomeSectionSubsectionClick(courseId: Parameter, courseName: Parameter, courseSection: Parameter, courseSubsection: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_courseHomeSectionSubsectionClick__courseId_courseIdcourseName_courseNamecourseSection_courseSectioncourseSubsection_courseSubsection(`courseId`, `courseName`, `courseSection`, `courseSubsection`), performs: perform) - } - public static func datesComponentTapped(courseId: Parameter, blockId: Parameter, link: Parameter, supported: Parameter, perform: @escaping (String, String, String, Bool) -> Void) -> Perform { - return Perform(method: .m_datesComponentTapped__courseId_courseIdblockId_blockIdlink_linksupported_supported(`courseId`, `blockId`, `link`, `supported`), performs: perform) - } - public static func calendarSyncToggle(enrollmentMode: Parameter, pacing: Parameter, courseId: Parameter, action: Parameter, perform: @escaping (EnrollmentMode, CoursePacing, String, CalendarDialogueAction) -> Void) -> Perform { - return Perform(method: .m_calendarSyncToggle__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdaction_action(`enrollmentMode`, `pacing`, `courseId`, `action`), performs: perform) - } - public static func calendarSyncDialogAction(enrollmentMode: Parameter, pacing: Parameter, courseId: Parameter, dialog: Parameter, action: Parameter, perform: @escaping (EnrollmentMode, CoursePacing, String, CalendarDialogueType, CalendarDialogueAction) -> Void) -> Perform { - return Perform(method: .m_calendarSyncDialogAction__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIddialog_dialogaction_action(`enrollmentMode`, `pacing`, `courseId`, `dialog`, `action`), performs: perform) - } - public static func calendarSyncSnackbar(enrollmentMode: Parameter, pacing: Parameter, courseId: Parameter, snackbar: Parameter, perform: @escaping (EnrollmentMode, CoursePacing, String, SnackbarType) -> Void) -> Perform { - return Perform(method: .m_calendarSyncSnackbar__enrollmentMode_enrollmentModepacing_pacingcourseId_courseIdsnackbar_snackbar(`enrollmentMode`, `pacing`, `courseId`, `snackbar`), performs: perform) - } - public static func trackCourseEvent(_ event: Parameter, biValue: Parameter, courseID: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String) -> Void) -> Perform { - return Perform(method: .m_trackCourseEvent__eventbiValue_biValuecourseID_courseID(`event`, `biValue`, `courseID`), performs: perform) - } - public static func trackCourseScreenEvent(_ event: Parameter, biValue: Parameter, courseID: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String) -> Void) -> Perform { - return Perform(method: .m_trackCourseScreenEvent__eventbiValue_biValuecourseID_courseID(`event`, `biValue`, `courseID`), performs: perform) - } - public static func plsEvent(_ event: Parameter, bivalue: Parameter, courseID: Parameter, screenName: Parameter, type: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String, String, String) -> Void) -> Perform { - return Perform(method: .m_plsEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_type(`event`, `bivalue`, `courseID`, `screenName`, `type`), performs: perform) - } - public static func plsSuccessEvent(_ event: Parameter, bivalue: Parameter, courseID: Parameter, screenName: Parameter, type: Parameter, success: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String, String, String, Bool) -> Void) -> Perform { - return Perform(method: .m_plsSuccessEvent__eventbivalue_bivaluecourseID_courseIDscreenName_screenNametype_typesuccess_success(`event`, `bivalue`, `courseID`, `screenName`, `type`, `success`), performs: perform) - } - public static func bulkDownloadVideosToggle(courseID: Parameter, action: Parameter, perform: @escaping (String, Bool) -> Void) -> Perform { - return Perform(method: .m_bulkDownloadVideosToggle__courseID_courseIDaction_action(`courseID`, `action`), performs: perform) - } - public static func bulkDownloadVideosSubsection(courseID: Parameter, sectionID: Parameter, subSectionID: Parameter, videos: Parameter, perform: @escaping (String, String, String, Int) -> Void) -> Perform { - return Perform(method: .m_bulkDownloadVideosSubsection__courseID_courseIDsectionID_sectionIDsubSectionID_subSectionIDvideos_videos(`courseID`, `sectionID`, `subSectionID`, `videos`), performs: perform) - } - public static func bulkDeleteVideosSubsection(courseID: Parameter, subSectionID: Parameter, videos: Parameter, perform: @escaping (String, String, Int) -> Void) -> Perform { - return Perform(method: .m_bulkDeleteVideosSubsection__courseID_courseIDsubSectionID_subSectionIDvideos_videos(`courseID`, `subSectionID`, `videos`), performs: perform) - } - public static func bulkDownloadVideosSection(courseID: Parameter, sectionID: Parameter, videos: Parameter, perform: @escaping (String, String, Int) -> Void) -> Perform { - return Perform(method: .m_bulkDownloadVideosSection__courseID_courseIDsectionID_sectionIDvideos_videos(`courseID`, `sectionID`, `videos`), performs: perform) - } - public static func bulkDeleteVideosSection(courseID: Parameter, sectionId: Parameter, videos: Parameter, perform: @escaping (String, String, Int) -> Void) -> Perform { - return Perform(method: .m_bulkDeleteVideosSection__courseID_courseIDsectionId_sectionIdvideos_videos(`courseID`, `sectionId`, `videos`), performs: perform) - } - public static func videoLoaded(courseID: Parameter, blockID: Parameter, videoURL: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_videoLoaded__courseID_courseIDblockID_blockIDvideoURL_videoURL(`courseID`, `blockID`, `videoURL`), performs: perform) - } - public static func videoPlayed(courseID: Parameter, blockID: Parameter, videoURL: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_videoPlayed__courseID_courseIDblockID_blockIDvideoURL_videoURL(`courseID`, `blockID`, `videoURL`), performs: perform) - } - public static func videoSpeedChange(courseID: Parameter, blockID: Parameter, videoURL: Parameter, oldSpeed: Parameter, newSpeed: Parameter, currentTime: Parameter, duration: Parameter, perform: @escaping (String, String, String, Float, Float, Double, Double) -> Void) -> Perform { - return Perform(method: .m_videoSpeedChange__courseID_courseIDblockID_blockIDvideoURL_videoURLoldSpeed_oldSpeednewSpeed_newSpeedcurrentTime_currentTimeduration_duration(`courseID`, `blockID`, `videoURL`, `oldSpeed`, `newSpeed`, `currentTime`, `duration`), performs: perform) - } - public static func videoPaused(courseID: Parameter, blockID: Parameter, videoURL: Parameter, currentTime: Parameter, duration: Parameter, perform: @escaping (String, String, String, Double, Double) -> Void) -> Perform { - return Perform(method: .m_videoPaused__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(`courseID`, `blockID`, `videoURL`, `currentTime`, `duration`), performs: perform) - } - public static func videoCompleted(courseID: Parameter, blockID: Parameter, videoURL: Parameter, currentTime: Parameter, duration: Parameter, perform: @escaping (String, String, String, Double, Double) -> Void) -> Perform { - return Perform(method: .m_videoCompleted__courseID_courseIDblockID_blockIDvideoURL_videoURLcurrentTime_currentTimeduration_duration(`courseID`, `blockID`, `videoURL`, `currentTime`, `duration`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CourseDownloadHelperProtocol - -open class CourseDownloadHelperProtocolMock: CourseDownloadHelperProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var value: CourseDownloadValue? { - get { invocations.append(.p_value_get); return __p_value ?? optionalGivenGetterValue(.p_value_get, "CourseDownloadHelperProtocolMock - stub value for value was not defined") } - } - private var __p_value: (CourseDownloadValue)? - - public var courseStructure: CourseStructure? { - get { invocations.append(.p_courseStructure_get); return __p_courseStructure ?? optionalGivenGetterValue(.p_courseStructure_get, "CourseDownloadHelperProtocolMock - stub value for courseStructure was not defined") } - set { invocations.append(.p_courseStructure_set(.value(newValue))); __p_courseStructure = newValue } - } - private var __p_courseStructure: (CourseStructure)? - - public var videoQuality: DownloadQuality { - get { invocations.append(.p_videoQuality_get); return __p_videoQuality ?? givenGetterValue(.p_videoQuality_get, "CourseDownloadHelperProtocolMock - stub value for videoQuality was not defined") } - set { invocations.append(.p_videoQuality_set(.value(newValue))); __p_videoQuality = newValue } - } - private var __p_videoQuality: (DownloadQuality)? - - - - - - open func publisher() -> AnyPublisher { - addInvocation(.m_publisher) - let perform = methodPerformValue(.m_publisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_publisher).casted() - } catch { - onFatalFailure("Stub return value not specified for publisher(). Use given") - Failure("Stub return value not specified for publisher(). Use given") - } - return __value - } - - open func progressPublisher() -> AnyPublisher { - addInvocation(.m_progressPublisher) - let perform = methodPerformValue(.m_progressPublisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_progressPublisher).casted() - } catch { - onFatalFailure("Stub return value not specified for progressPublisher(). Use given") - Failure("Stub return value not specified for progressPublisher(). Use given") - } - return __value - } - - open func refreshValue() { - addInvocation(.m_refreshValue) - let perform = methodPerformValue(.m_refreshValue) as? () -> Void - perform?() - } - - open func sizeFor(block: CourseBlock) -> Int? { - addInvocation(.m_sizeFor__block_block(Parameter.value(`block`))) - let perform = methodPerformValue(.m_sizeFor__block_block(Parameter.value(`block`))) as? (CourseBlock) -> Void - perform?(`block`) - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_sizeFor__block_block(Parameter.value(`block`))).casted() - } catch { - // do nothing - } - return __value - } - - open func sizeFor(blocks: [CourseBlock]) -> Int { - addInvocation(.m_sizeFor__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_sizeFor__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - var __value: Int - do { - __value = try methodReturnValue(.m_sizeFor__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() - } catch { - onFatalFailure("Stub return value not specified for sizeFor(blocks: [CourseBlock]). Use given") - Failure("Stub return value not specified for sizeFor(blocks: [CourseBlock]). Use given") - } - return __value - } - - open func sizeFor(sequential: CourseSequential) -> Int { - addInvocation(.m_sizeFor__sequential_sequential(Parameter.value(`sequential`))) - let perform = methodPerformValue(.m_sizeFor__sequential_sequential(Parameter.value(`sequential`))) as? (CourseSequential) -> Void - perform?(`sequential`) - var __value: Int - do { - __value = try methodReturnValue(.m_sizeFor__sequential_sequential(Parameter.value(`sequential`))).casted() - } catch { - onFatalFailure("Stub return value not specified for sizeFor(sequential: CourseSequential). Use given") - Failure("Stub return value not specified for sizeFor(sequential: CourseSequential). Use given") - } - return __value - } - - open func sizeFor(sequentials: [CourseSequential]) -> Int { - addInvocation(.m_sizeFor__sequentials_sequentials(Parameter<[CourseSequential]>.value(`sequentials`))) - let perform = methodPerformValue(.m_sizeFor__sequentials_sequentials(Parameter<[CourseSequential]>.value(`sequentials`))) as? ([CourseSequential]) -> Void - perform?(`sequentials`) - var __value: Int - do { - __value = try methodReturnValue(.m_sizeFor__sequentials_sequentials(Parameter<[CourseSequential]>.value(`sequentials`))).casted() - } catch { - onFatalFailure("Stub return value not specified for sizeFor(sequentials: [CourseSequential]). Use given") - Failure("Stub return value not specified for sizeFor(sequentials: [CourseSequential]). Use given") - } - return __value - } - - open func cancelDownloading(task: DownloadDataTask) throws { - addInvocation(.m_cancelDownloading__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_cancelDownloading__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - do { - _ = try methodReturnValue(.m_cancelDownloading__task_task(Parameter.value(`task`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - - fileprivate enum MethodType { - case m_publisher - case m_progressPublisher - case m_refreshValue - case m_sizeFor__block_block(Parameter) - case m_sizeFor__blocks_blocks(Parameter<[CourseBlock]>) - case m_sizeFor__sequential_sequential(Parameter) - case m_sizeFor__sequentials_sequentials(Parameter<[CourseSequential]>) - case m_cancelDownloading__task_task(Parameter) - case p_value_get - case p_courseStructure_get - case p_courseStructure_set(Parameter) - case p_videoQuality_get - case p_videoQuality_set(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_publisher, .m_publisher): return .match - - case (.m_progressPublisher, .m_progressPublisher): return .match - - case (.m_refreshValue, .m_refreshValue): return .match - - case (.m_sizeFor__block_block(let lhsBlock), .m_sizeFor__block_block(let rhsBlock)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlock, rhs: rhsBlock, with: matcher), lhsBlock, rhsBlock, "block")) - return Matcher.ComparisonResult(results) - - case (.m_sizeFor__blocks_blocks(let lhsBlocks), .m_sizeFor__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_sizeFor__sequential_sequential(let lhsSequential), .m_sizeFor__sequential_sequential(let rhsSequential)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSequential, rhs: rhsSequential, with: matcher), lhsSequential, rhsSequential, "sequential")) - return Matcher.ComparisonResult(results) - - case (.m_sizeFor__sequentials_sequentials(let lhsSequentials), .m_sizeFor__sequentials_sequentials(let rhsSequentials)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSequentials, rhs: rhsSequentials, with: matcher), lhsSequentials, rhsSequentials, "sequentials")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__task_task(let lhsTask), .m_cancelDownloading__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - case (.p_value_get,.p_value_get): return Matcher.ComparisonResult.match - case (.p_courseStructure_get,.p_courseStructure_get): return Matcher.ComparisonResult.match - case (.p_courseStructure_set(let left),.p_courseStructure_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_videoQuality_get,.p_videoQuality_get): return Matcher.ComparisonResult.match - case (.p_videoQuality_set(let left),.p_videoQuality_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_publisher: return 0 - case .m_progressPublisher: return 0 - case .m_refreshValue: return 0 - case let .m_sizeFor__block_block(p0): return p0.intValue - case let .m_sizeFor__blocks_blocks(p0): return p0.intValue - case let .m_sizeFor__sequential_sequential(p0): return p0.intValue - case let .m_sizeFor__sequentials_sequentials(p0): return p0.intValue - case let .m_cancelDownloading__task_task(p0): return p0.intValue - case .p_value_get: return 0 - case .p_courseStructure_get: return 0 - case .p_courseStructure_set(let newValue): return newValue.intValue - case .p_videoQuality_get: return 0 - case .p_videoQuality_set(let newValue): return newValue.intValue - } - } - func assertionName() -> String { - switch self { - case .m_publisher: return ".publisher()" - case .m_progressPublisher: return ".progressPublisher()" - case .m_refreshValue: return ".refreshValue()" - case .m_sizeFor__block_block: return ".sizeFor(block:)" - case .m_sizeFor__blocks_blocks: return ".sizeFor(blocks:)" - case .m_sizeFor__sequential_sequential: return ".sizeFor(sequential:)" - case .m_sizeFor__sequentials_sequentials: return ".sizeFor(sequentials:)" - case .m_cancelDownloading__task_task: return ".cancelDownloading(task:)" - case .p_value_get: return "[get] .value" - case .p_courseStructure_get: return "[get] .courseStructure" - case .p_courseStructure_set: return "[set] .courseStructure" - case .p_videoQuality_get: return "[get] .videoQuality" - case .p_videoQuality_set: return "[set] .videoQuality" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func value(getter defaultValue: CourseDownloadValue?...) -> PropertyStub { - return Given(method: .p_value_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func courseStructure(getter defaultValue: CourseStructure?...) -> PropertyStub { - return Given(method: .p_courseStructure_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func videoQuality(getter defaultValue: DownloadQuality...) -> PropertyStub { - return Given(method: .p_videoQuality_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - public static func publisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_publisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func progressPublisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_progressPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func sizeFor(block: Parameter, willReturn: Int?...) -> MethodStub { - return Given(method: .m_sizeFor__block_block(`block`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func sizeFor(blocks: Parameter<[CourseBlock]>, willReturn: Int...) -> MethodStub { - return Given(method: .m_sizeFor__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func sizeFor(sequential: Parameter, willReturn: Int...) -> MethodStub { - return Given(method: .m_sizeFor__sequential_sequential(`sequential`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func sizeFor(sequentials: Parameter<[CourseSequential]>, willReturn: Int...) -> MethodStub { - return Given(method: .m_sizeFor__sequentials_sequentials(`sequentials`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func publisher(willProduce: (Stubber>) -> Void) -> MethodStub { - let willReturn: [AnyPublisher] = [] - let given: Given = { return Given(method: .m_publisher, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - public static func progressPublisher(willProduce: (Stubber>) -> Void) -> MethodStub { - let willReturn: [AnyPublisher] = [] - let given: Given = { return Given(method: .m_progressPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - public static func sizeFor(block: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_sizeFor__block_block(`block`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func sizeFor(blocks: Parameter<[CourseBlock]>, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int] = [] - let given: Given = { return Given(method: .m_sizeFor__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int).self) - willProduce(stubber) - return given - } - public static func sizeFor(sequential: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int] = [] - let given: Given = { return Given(method: .m_sizeFor__sequential_sequential(`sequential`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int).self) - willProduce(stubber) - return given - } - public static func sizeFor(sequentials: Parameter<[CourseSequential]>, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int] = [] - let given: Given = { return Given(method: .m_sizeFor__sequentials_sequentials(`sequentials`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(task: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(task: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func publisher() -> Verify { return Verify(method: .m_publisher)} - public static func progressPublisher() -> Verify { return Verify(method: .m_progressPublisher)} - public static func refreshValue() -> Verify { return Verify(method: .m_refreshValue)} - public static func sizeFor(block: Parameter) -> Verify { return Verify(method: .m_sizeFor__block_block(`block`))} - public static func sizeFor(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_sizeFor__blocks_blocks(`blocks`))} - public static func sizeFor(sequential: Parameter) -> Verify { return Verify(method: .m_sizeFor__sequential_sequential(`sequential`))} - public static func sizeFor(sequentials: Parameter<[CourseSequential]>) -> Verify { return Verify(method: .m_sizeFor__sequentials_sequentials(`sequentials`))} - public static func cancelDownloading(task: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__task_task(`task`))} - public static var value: Verify { return Verify(method: .p_value_get) } - public static var courseStructure: Verify { return Verify(method: .p_courseStructure_get) } - public static func courseStructure(set newValue: Parameter) -> Verify { return Verify(method: .p_courseStructure_set(newValue)) } - public static var videoQuality: Verify { return Verify(method: .p_videoQuality_get) } - public static func videoQuality(set newValue: Parameter) -> Verify { return Verify(method: .p_videoQuality_set(newValue)) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func publisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_publisher, performs: perform) - } - public static func progressPublisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_progressPublisher, performs: perform) - } - public static func refreshValue(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_refreshValue, performs: perform) - } - public static func sizeFor(block: Parameter, perform: @escaping (CourseBlock) -> Void) -> Perform { - return Perform(method: .m_sizeFor__block_block(`block`), performs: perform) - } - public static func sizeFor(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_sizeFor__blocks_blocks(`blocks`), performs: perform) - } - public static func sizeFor(sequential: Parameter, perform: @escaping (CourseSequential) -> Void) -> Perform { - return Perform(method: .m_sizeFor__sequential_sequential(`sequential`), performs: perform) - } - public static func sizeFor(sequentials: Parameter<[CourseSequential]>, perform: @escaping ([CourseSequential]) -> Void) -> Perform { - return Perform(method: .m_sizeFor__sequentials_sequentials(`sequentials`), performs: perform) - } - public static func cancelDownloading(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__task_task(`task`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CourseInteractorProtocol - -open class CourseInteractorProtocolMock: CourseInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCourseVideoBlocks(fullStructure: CourseStructure) -> CourseStructure { - addInvocation(.m_getCourseVideoBlocks__fullStructure_fullStructure(Parameter.value(`fullStructure`))) - let perform = methodPerformValue(.m_getCourseVideoBlocks__fullStructure_fullStructure(Parameter.value(`fullStructure`))) as? (CourseStructure) -> Void - perform?(`fullStructure`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getCourseVideoBlocks__fullStructure_fullStructure(Parameter.value(`fullStructure`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getCourseVideoBlocks(fullStructure: CourseStructure). Use given") - Failure("Stub return value not specified for getCourseVideoBlocks(fullStructure: CourseStructure). Use given") - } - return __value - } - - open func getCourseAssignmentBlocks(fullStructure: CourseStructure) -> CourseStructure { - addInvocation(.m_getCourseAssignmentBlocks__fullStructure_fullStructure(Parameter.value(`fullStructure`))) - let perform = methodPerformValue(.m_getCourseAssignmentBlocks__fullStructure_fullStructure(Parameter.value(`fullStructure`))) as? (CourseStructure) -> Void - perform?(`fullStructure`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getCourseAssignmentBlocks__fullStructure_fullStructure(Parameter.value(`fullStructure`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getCourseAssignmentBlocks(fullStructure: CourseStructure). Use given") - Failure("Stub return value not specified for getCourseAssignmentBlocks(fullStructure: CourseStructure). Use given") - } - return __value - } - - open func getLoadedCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getSequentialsContainsBlocks(blockIds: [String], courseID: String) throws -> [CourseSequential] { - addInvocation(.m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID(Parameter<[String]>.value(`blockIds`), Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID(Parameter<[String]>.value(`blockIds`), Parameter.value(`courseID`))) as? ([String], String) -> Void - perform?(`blockIds`, `courseID`) - var __value: [CourseSequential] - do { - __value = try methodReturnValue(.m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID(Parameter<[String]>.value(`blockIds`), Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getSequentialsContainsBlocks(blockIds: [String], courseID: String). Use given") - Failure("Stub return value not specified for getSequentialsContainsBlocks(blockIds: [String], courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func blockCompletionRequest(courseID: String, blockID: String) throws { - addInvocation(.m_blockCompletionRequest__courseID_courseIDblockID_blockID(Parameter.value(`courseID`), Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_blockCompletionRequest__courseID_courseIDblockID_blockID(Parameter.value(`courseID`), Parameter.value(`blockID`))) as? (String, String) -> Void - perform?(`courseID`, `blockID`) - do { - _ = try methodReturnValue(.m_blockCompletionRequest__courseID_courseIDblockID_blockID(Parameter.value(`courseID`), Parameter.value(`blockID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getHandouts(courseID: String) throws -> String? { - addInvocation(.m_getHandouts__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getHandouts__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: String? = nil - do { - __value = try methodReturnValue(.m_getHandouts__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - return __value - } - - open func getUpdates(courseID: String) throws -> [CourseUpdate] { - addInvocation(.m_getUpdates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getUpdates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: [CourseUpdate] - do { - __value = try methodReturnValue(.m_getUpdates__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getUpdates(courseID: String). Use given") - Failure("Stub return value not specified for getUpdates(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func resumeBlock(courseID: String) throws -> ResumeBlock { - addInvocation(.m_resumeBlock__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_resumeBlock__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: ResumeBlock - do { - __value = try methodReturnValue(.m_resumeBlock__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for resumeBlock(courseID: String). Use given") - Failure("Stub return value not specified for resumeBlock(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getSubtitles(url: String, selectedLanguage: String) throws -> [Subtitle] { - addInvocation(.m_getSubtitles__url_urlselectedLanguage_selectedLanguage(Parameter.value(`url`), Parameter.value(`selectedLanguage`))) - let perform = methodPerformValue(.m_getSubtitles__url_urlselectedLanguage_selectedLanguage(Parameter.value(`url`), Parameter.value(`selectedLanguage`))) as? (String, String) -> Void - perform?(`url`, `selectedLanguage`) - var __value: [Subtitle] - do { - __value = try methodReturnValue(.m_getSubtitles__url_urlselectedLanguage_selectedLanguage(Parameter.value(`url`), Parameter.value(`selectedLanguage`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getSubtitles(url: String, selectedLanguage: String). Use given") - Failure("Stub return value not specified for getSubtitles(url: String, selectedLanguage: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCourseDates(courseID: String) throws -> CourseDates { - addInvocation(.m_getCourseDates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseDates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseDates - do { - __value = try methodReturnValue(.m_getCourseDates__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseDates(courseID: String). Use given") - Failure("Stub return value not specified for getCourseDates(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCourseDeadlineInfo(courseID: String) throws -> CourseDateBanner { - addInvocation(.m_getCourseDeadlineInfo__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseDeadlineInfo__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseDateBanner - do { - __value = try methodReturnValue(.m_getCourseDeadlineInfo__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseDeadlineInfo(courseID: String). Use given") - Failure("Stub return value not specified for getCourseDeadlineInfo(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func shiftDueDates(courseID: String) throws { - addInvocation(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - do { - _ = try methodReturnValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func updateLocalVideoProgress(blockID: String, progress: Double) { - addInvocation(.m_updateLocalVideoProgress__blockID_blockIDprogress_progress(Parameter.value(`blockID`), Parameter.value(`progress`))) - let perform = methodPerformValue(.m_updateLocalVideoProgress__blockID_blockIDprogress_progress(Parameter.value(`blockID`), Parameter.value(`progress`))) as? (String, Double) -> Void - perform?(`blockID`, `progress`) - } - - open func loadLocalVideoProgress(blockID: String) -> Double? { - addInvocation(.m_loadLocalVideoProgress__blockID_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_loadLocalVideoProgress__blockID_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - var __value: Double? = nil - do { - __value = try methodReturnValue(.m_loadLocalVideoProgress__blockID_blockID(Parameter.value(`blockID`))).casted() - } catch { - // do nothing - } - return __value - } - - open func enrichCourseStructureWithLocalProgress(_ structure: CourseStructure) -> CourseStructure { - addInvocation(.m_enrichCourseStructureWithLocalProgress__structure(Parameter.value(`structure`))) - let perform = methodPerformValue(.m_enrichCourseStructureWithLocalProgress__structure(Parameter.value(`structure`))) as? (CourseStructure) -> Void - perform?(`structure`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_enrichCourseStructureWithLocalProgress__structure(Parameter.value(`structure`))).casted() - } catch { - onFatalFailure("Stub return value not specified for enrichCourseStructureWithLocalProgress(_ structure: CourseStructure). Use given") - Failure("Stub return value not specified for enrichCourseStructureWithLocalProgress(_ structure: CourseStructure). Use given") - } - return __value - } - - open func getCourseProgress(courseID: String) throws -> CourseProgressDetails { - addInvocation(.m_getCourseProgress__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseProgress__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseProgressDetails - do { - __value = try methodReturnValue(.m_getCourseProgress__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseProgress(courseID: String). Use given") - Failure("Stub return value not specified for getCourseProgress(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCourseProgressOffline(courseID: String) throws -> CourseProgressDetails { - addInvocation(.m_getCourseProgressOffline__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseProgressOffline__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseProgressDetails - do { - __value = try methodReturnValue(.m_getCourseProgressOffline__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseProgressOffline(courseID: String). Use given") - Failure("Stub return value not specified for getCourseProgressOffline(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getAllVideosForNavigation(structure course: CourseStructure) throws -> [CourseBlock] { - addInvocation(.m_getAllVideosForNavigation__structure_course(Parameter.value(`course`))) - let perform = methodPerformValue(.m_getAllVideosForNavigation__structure_course(Parameter.value(`course`))) as? (CourseStructure) -> Void - perform?(`course`) - var __value: [CourseBlock] - do { - __value = try methodReturnValue(.m_getAllVideosForNavigation__structure_course(Parameter.value(`course`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getAllVideosForNavigation(structure course: CourseStructure). Use given") - Failure("Stub return value not specified for getAllVideosForNavigation(structure course: CourseStructure). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_getCourseBlocks__courseID_courseID(Parameter) - case m_getCourseVideoBlocks__fullStructure_fullStructure(Parameter) - case m_getCourseAssignmentBlocks__fullStructure_fullStructure(Parameter) - case m_getLoadedCourseBlocks__courseID_courseID(Parameter) - case m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID(Parameter<[String]>, Parameter) - case m_blockCompletionRequest__courseID_courseIDblockID_blockID(Parameter, Parameter) - case m_getHandouts__courseID_courseID(Parameter) - case m_getUpdates__courseID_courseID(Parameter) - case m_resumeBlock__courseID_courseID(Parameter) - case m_getSubtitles__url_urlselectedLanguage_selectedLanguage(Parameter, Parameter) - case m_getCourseDates__courseID_courseID(Parameter) - case m_getCourseDeadlineInfo__courseID_courseID(Parameter) - case m_shiftDueDates__courseID_courseID(Parameter) - case m_updateLocalVideoProgress__blockID_blockIDprogress_progress(Parameter, Parameter) - case m_loadLocalVideoProgress__blockID_blockID(Parameter) - case m_enrichCourseStructureWithLocalProgress__structure(Parameter) - case m_getCourseProgress__courseID_courseID(Parameter) - case m_getCourseProgressOffline__courseID_courseID(Parameter) - case m_getAllVideosForNavigation__structure_course(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseBlocks__courseID_courseID(let lhsCourseid), .m_getCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getCourseVideoBlocks__fullStructure_fullStructure(let lhsFullstructure), .m_getCourseVideoBlocks__fullStructure_fullStructure(let rhsFullstructure)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFullstructure, rhs: rhsFullstructure, with: matcher), lhsFullstructure, rhsFullstructure, "fullStructure")) - return Matcher.ComparisonResult(results) - - case (.m_getCourseAssignmentBlocks__fullStructure_fullStructure(let lhsFullstructure), .m_getCourseAssignmentBlocks__fullStructure_fullStructure(let rhsFullstructure)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFullstructure, rhs: rhsFullstructure, with: matcher), lhsFullstructure, rhsFullstructure, "fullStructure")) - return Matcher.ComparisonResult(results) - - case (.m_getLoadedCourseBlocks__courseID_courseID(let lhsCourseid), .m_getLoadedCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID(let lhsBlockids, let lhsCourseid), .m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID(let rhsBlockids, let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockids, rhs: rhsBlockids, with: matcher), lhsBlockids, rhsBlockids, "blockIds")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_blockCompletionRequest__courseID_courseIDblockID_blockID(let lhsCourseid, let lhsBlockid), .m_blockCompletionRequest__courseID_courseIDblockID_blockID(let rhsCourseid, let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - return Matcher.ComparisonResult(results) - - case (.m_getHandouts__courseID_courseID(let lhsCourseid), .m_getHandouts__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getUpdates__courseID_courseID(let lhsCourseid), .m_getUpdates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_resumeBlock__courseID_courseID(let lhsCourseid), .m_resumeBlock__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getSubtitles__url_urlselectedLanguage_selectedLanguage(let lhsUrl, let lhsSelectedlanguage), .m_getSubtitles__url_urlselectedLanguage_selectedLanguage(let rhsUrl, let rhsSelectedlanguage)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSelectedlanguage, rhs: rhsSelectedlanguage, with: matcher), lhsSelectedlanguage, rhsSelectedlanguage, "selectedLanguage")) - return Matcher.ComparisonResult(results) - - case (.m_getCourseDates__courseID_courseID(let lhsCourseid), .m_getCourseDates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getCourseDeadlineInfo__courseID_courseID(let lhsCourseid), .m_getCourseDeadlineInfo__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_shiftDueDates__courseID_courseID(let lhsCourseid), .m_shiftDueDates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_updateLocalVideoProgress__blockID_blockIDprogress_progress(let lhsBlockid, let lhsProgress), .m_updateLocalVideoProgress__blockID_blockIDprogress_progress(let rhsBlockid, let rhsProgress)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsProgress, rhs: rhsProgress, with: matcher), lhsProgress, rhsProgress, "progress")) - return Matcher.ComparisonResult(results) - - case (.m_loadLocalVideoProgress__blockID_blockID(let lhsBlockid), .m_loadLocalVideoProgress__blockID_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - return Matcher.ComparisonResult(results) - - case (.m_enrichCourseStructureWithLocalProgress__structure(let lhsStructure), .m_enrichCourseStructureWithLocalProgress__structure(let rhsStructure)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsStructure, rhs: rhsStructure, with: matcher), lhsStructure, rhsStructure, "_ structure")) - return Matcher.ComparisonResult(results) - - case (.m_getCourseProgress__courseID_courseID(let lhsCourseid), .m_getCourseProgress__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getCourseProgressOffline__courseID_courseID(let lhsCourseid), .m_getCourseProgressOffline__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getAllVideosForNavigation__structure_course(let lhsCourse), .m_getAllVideosForNavigation__structure_course(let rhsCourse)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourse, rhs: rhsCourse, with: matcher), lhsCourse, rhsCourse, "structure course")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_getCourseVideoBlocks__fullStructure_fullStructure(p0): return p0.intValue - case let .m_getCourseAssignmentBlocks__fullStructure_fullStructure(p0): return p0.intValue - case let .m_getLoadedCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID(p0, p1): return p0.intValue + p1.intValue - case let .m_blockCompletionRequest__courseID_courseIDblockID_blockID(p0, p1): return p0.intValue + p1.intValue - case let .m_getHandouts__courseID_courseID(p0): return p0.intValue - case let .m_getUpdates__courseID_courseID(p0): return p0.intValue - case let .m_resumeBlock__courseID_courseID(p0): return p0.intValue - case let .m_getSubtitles__url_urlselectedLanguage_selectedLanguage(p0, p1): return p0.intValue + p1.intValue - case let .m_getCourseDates__courseID_courseID(p0): return p0.intValue - case let .m_getCourseDeadlineInfo__courseID_courseID(p0): return p0.intValue - case let .m_shiftDueDates__courseID_courseID(p0): return p0.intValue - case let .m_updateLocalVideoProgress__blockID_blockIDprogress_progress(p0, p1): return p0.intValue + p1.intValue - case let .m_loadLocalVideoProgress__blockID_blockID(p0): return p0.intValue - case let .m_enrichCourseStructureWithLocalProgress__structure(p0): return p0.intValue - case let .m_getCourseProgress__courseID_courseID(p0): return p0.intValue - case let .m_getCourseProgressOffline__courseID_courseID(p0): return p0.intValue - case let .m_getAllVideosForNavigation__structure_course(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getCourseBlocks__courseID_courseID: return ".getCourseBlocks(courseID:)" - case .m_getCourseVideoBlocks__fullStructure_fullStructure: return ".getCourseVideoBlocks(fullStructure:)" - case .m_getCourseAssignmentBlocks__fullStructure_fullStructure: return ".getCourseAssignmentBlocks(fullStructure:)" - case .m_getLoadedCourseBlocks__courseID_courseID: return ".getLoadedCourseBlocks(courseID:)" - case .m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID: return ".getSequentialsContainsBlocks(blockIds:courseID:)" - case .m_blockCompletionRequest__courseID_courseIDblockID_blockID: return ".blockCompletionRequest(courseID:blockID:)" - case .m_getHandouts__courseID_courseID: return ".getHandouts(courseID:)" - case .m_getUpdates__courseID_courseID: return ".getUpdates(courseID:)" - case .m_resumeBlock__courseID_courseID: return ".resumeBlock(courseID:)" - case .m_getSubtitles__url_urlselectedLanguage_selectedLanguage: return ".getSubtitles(url:selectedLanguage:)" - case .m_getCourseDates__courseID_courseID: return ".getCourseDates(courseID:)" - case .m_getCourseDeadlineInfo__courseID_courseID: return ".getCourseDeadlineInfo(courseID:)" - case .m_shiftDueDates__courseID_courseID: return ".shiftDueDates(courseID:)" - case .m_updateLocalVideoProgress__blockID_blockIDprogress_progress: return ".updateLocalVideoProgress(blockID:progress:)" - case .m_loadLocalVideoProgress__blockID_blockID: return ".loadLocalVideoProgress(blockID:)" - case .m_enrichCourseStructureWithLocalProgress__structure: return ".enrichCourseStructureWithLocalProgress(_:)" - case .m_getCourseProgress__courseID_courseID: return ".getCourseProgress(courseID:)" - case .m_getCourseProgressOffline__courseID_courseID: return ".getCourseProgressOffline(courseID:)" - case .m_getAllVideosForNavigation__structure_course: return ".getAllVideosForNavigation(structure:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseVideoBlocks(fullStructure: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getCourseVideoBlocks__fullStructure_fullStructure(`fullStructure`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseAssignmentBlocks(fullStructure: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getCourseAssignmentBlocks__fullStructure_fullStructure(`fullStructure`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getSequentialsContainsBlocks(blockIds: Parameter<[String]>, courseID: Parameter, willReturn: [CourseSequential]...) -> MethodStub { - return Given(method: .m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID(`blockIds`, `courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getHandouts(courseID: Parameter, willReturn: String?...) -> MethodStub { - return Given(method: .m_getHandouts__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getUpdates(courseID: Parameter, willReturn: [CourseUpdate]...) -> MethodStub { - return Given(method: .m_getUpdates__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func resumeBlock(courseID: Parameter, willReturn: ResumeBlock...) -> MethodStub { - return Given(method: .m_resumeBlock__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getSubtitles(url: Parameter, selectedLanguage: Parameter, willReturn: [Subtitle]...) -> MethodStub { - return Given(method: .m_getSubtitles__url_urlselectedLanguage_selectedLanguage(`url`, `selectedLanguage`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseDates(courseID: Parameter, willReturn: CourseDates...) -> MethodStub { - return Given(method: .m_getCourseDates__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseDeadlineInfo(courseID: Parameter, willReturn: CourseDateBanner...) -> MethodStub { - return Given(method: .m_getCourseDeadlineInfo__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadLocalVideoProgress(blockID: Parameter, willReturn: Double?...) -> MethodStub { - return Given(method: .m_loadLocalVideoProgress__blockID_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func enrichCourseStructureWithLocalProgress(_ structure: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_enrichCourseStructureWithLocalProgress__structure(`structure`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseProgress(courseID: Parameter, willReturn: CourseProgressDetails...) -> MethodStub { - return Given(method: .m_getCourseProgress__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseProgressOffline(courseID: Parameter, willReturn: CourseProgressDetails...) -> MethodStub { - return Given(method: .m_getCourseProgressOffline__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getAllVideosForNavigation(structure course: Parameter, willReturn: [CourseBlock]...) -> MethodStub { - return Given(method: .m_getAllVideosForNavigation__structure_course(`course`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseVideoBlocks(fullStructure: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [CourseStructure] = [] - let given: Given = { return Given(method: .m_getCourseVideoBlocks__fullStructure_fullStructure(`fullStructure`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getCourseAssignmentBlocks(fullStructure: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [CourseStructure] = [] - let given: Given = { return Given(method: .m_getCourseAssignmentBlocks__fullStructure_fullStructure(`fullStructure`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func loadLocalVideoProgress(blockID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Double?] = [] - let given: Given = { return Given(method: .m_loadLocalVideoProgress__blockID_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Double?).self) - willProduce(stubber) - return given - } - public static func enrichCourseStructureWithLocalProgress(_ structure: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [CourseStructure] = [] - let given: Given = { return Given(method: .m_enrichCourseStructureWithLocalProgress__structure(`structure`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getLoadedCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getSequentialsContainsBlocks(blockIds: Parameter<[String]>, courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID(`blockIds`, `courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getSequentialsContainsBlocks(blockIds: Parameter<[String]>, courseID: Parameter, willProduce: (StubberThrows<[CourseSequential]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID(`blockIds`, `courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([CourseSequential]).self) - willProduce(stubber) - return given - } - public static func blockCompletionRequest(courseID: Parameter, blockID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_blockCompletionRequest__courseID_courseIDblockID_blockID(`courseID`, `blockID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func blockCompletionRequest(courseID: Parameter, blockID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_blockCompletionRequest__courseID_courseIDblockID_blockID(`courseID`, `blockID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func getHandouts(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getHandouts__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getHandouts(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getHandouts__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (String?).self) - willProduce(stubber) - return given - } - public static func getUpdates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getUpdates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getUpdates(courseID: Parameter, willProduce: (StubberThrows<[CourseUpdate]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getUpdates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([CourseUpdate]).self) - willProduce(stubber) - return given - } - public static func resumeBlock(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_resumeBlock__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resumeBlock(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resumeBlock__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (ResumeBlock).self) - willProduce(stubber) - return given - } - public static func getSubtitles(url: Parameter, selectedLanguage: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getSubtitles__url_urlselectedLanguage_selectedLanguage(`url`, `selectedLanguage`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getSubtitles(url: Parameter, selectedLanguage: Parameter, willProduce: (StubberThrows<[Subtitle]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getSubtitles__url_urlselectedLanguage_selectedLanguage(`url`, `selectedLanguage`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([Subtitle]).self) - willProduce(stubber) - return given - } - public static func getCourseDates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseDates(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseDates).self) - willProduce(stubber) - return given - } - public static func getCourseDeadlineInfo(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseDeadlineInfo__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseDeadlineInfo(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseDeadlineInfo__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseDateBanner).self) - willProduce(stubber) - return given - } - public static func shiftDueDates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func shiftDueDates(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func getCourseProgress(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseProgress__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseProgress(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseProgress__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseProgressDetails).self) - willProduce(stubber) - return given - } - public static func getCourseProgressOffline(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseProgressOffline__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseProgressOffline(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseProgressOffline__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseProgressDetails).self) - willProduce(stubber) - return given - } - public static func getAllVideosForNavigation(structure course: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getAllVideosForNavigation__structure_course(`course`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getAllVideosForNavigation(structure course: Parameter, willProduce: (StubberThrows<[CourseBlock]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getAllVideosForNavigation__structure_course(`course`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([CourseBlock]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseBlocks__courseID_courseID(`courseID`))} - public static func getCourseVideoBlocks(fullStructure: Parameter) -> Verify { return Verify(method: .m_getCourseVideoBlocks__fullStructure_fullStructure(`fullStructure`))} - public static func getCourseAssignmentBlocks(fullStructure: Parameter) -> Verify { return Verify(method: .m_getCourseAssignmentBlocks__fullStructure_fullStructure(`fullStructure`))} - public static func getLoadedCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`))} - public static func getSequentialsContainsBlocks(blockIds: Parameter<[String]>, courseID: Parameter) -> Verify { return Verify(method: .m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID(`blockIds`, `courseID`))} - public static func blockCompletionRequest(courseID: Parameter, blockID: Parameter) -> Verify { return Verify(method: .m_blockCompletionRequest__courseID_courseIDblockID_blockID(`courseID`, `blockID`))} - public static func getHandouts(courseID: Parameter) -> Verify { return Verify(method: .m_getHandouts__courseID_courseID(`courseID`))} - public static func getUpdates(courseID: Parameter) -> Verify { return Verify(method: .m_getUpdates__courseID_courseID(`courseID`))} - public static func resumeBlock(courseID: Parameter) -> Verify { return Verify(method: .m_resumeBlock__courseID_courseID(`courseID`))} - public static func getSubtitles(url: Parameter, selectedLanguage: Parameter) -> Verify { return Verify(method: .m_getSubtitles__url_urlselectedLanguage_selectedLanguage(`url`, `selectedLanguage`))} - public static func getCourseDates(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseDates__courseID_courseID(`courseID`))} - public static func getCourseDeadlineInfo(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseDeadlineInfo__courseID_courseID(`courseID`))} - public static func shiftDueDates(courseID: Parameter) -> Verify { return Verify(method: .m_shiftDueDates__courseID_courseID(`courseID`))} - public static func updateLocalVideoProgress(blockID: Parameter, progress: Parameter) -> Verify { return Verify(method: .m_updateLocalVideoProgress__blockID_blockIDprogress_progress(`blockID`, `progress`))} - public static func loadLocalVideoProgress(blockID: Parameter) -> Verify { return Verify(method: .m_loadLocalVideoProgress__blockID_blockID(`blockID`))} - public static func enrichCourseStructureWithLocalProgress(_ structure: Parameter) -> Verify { return Verify(method: .m_enrichCourseStructureWithLocalProgress__structure(`structure`))} - public static func getCourseProgress(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseProgress__courseID_courseID(`courseID`))} - public static func getCourseProgressOffline(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseProgressOffline__courseID_courseID(`courseID`))} - public static func getAllVideosForNavigation(structure course: Parameter) -> Verify { return Verify(method: .m_getAllVideosForNavigation__structure_course(`course`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func getCourseVideoBlocks(fullStructure: Parameter, perform: @escaping (CourseStructure) -> Void) -> Perform { - return Perform(method: .m_getCourseVideoBlocks__fullStructure_fullStructure(`fullStructure`), performs: perform) - } - public static func getCourseAssignmentBlocks(fullStructure: Parameter, perform: @escaping (CourseStructure) -> Void) -> Perform { - return Perform(method: .m_getCourseAssignmentBlocks__fullStructure_fullStructure(`fullStructure`), performs: perform) - } - public static func getLoadedCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func getSequentialsContainsBlocks(blockIds: Parameter<[String]>, courseID: Parameter, perform: @escaping ([String], String) -> Void) -> Perform { - return Perform(method: .m_getSequentialsContainsBlocks__blockIds_blockIdscourseID_courseID(`blockIds`, `courseID`), performs: perform) - } - public static func blockCompletionRequest(courseID: Parameter, blockID: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_blockCompletionRequest__courseID_courseIDblockID_blockID(`courseID`, `blockID`), performs: perform) - } - public static func getHandouts(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getHandouts__courseID_courseID(`courseID`), performs: perform) - } - public static func getUpdates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getUpdates__courseID_courseID(`courseID`), performs: perform) - } - public static func resumeBlock(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_resumeBlock__courseID_courseID(`courseID`), performs: perform) - } - public static func getSubtitles(url: Parameter, selectedLanguage: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_getSubtitles__url_urlselectedLanguage_selectedLanguage(`url`, `selectedLanguage`), performs: perform) - } - public static func getCourseDates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseDates__courseID_courseID(`courseID`), performs: perform) - } - public static func getCourseDeadlineInfo(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseDeadlineInfo__courseID_courseID(`courseID`), performs: perform) - } - public static func shiftDueDates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_shiftDueDates__courseID_courseID(`courseID`), performs: perform) - } - public static func updateLocalVideoProgress(blockID: Parameter, progress: Parameter, perform: @escaping (String, Double) -> Void) -> Perform { - return Perform(method: .m_updateLocalVideoProgress__blockID_blockIDprogress_progress(`blockID`, `progress`), performs: perform) - } - public static func loadLocalVideoProgress(blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_loadLocalVideoProgress__blockID_blockID(`blockID`), performs: perform) - } - public static func enrichCourseStructureWithLocalProgress(_ structure: Parameter, perform: @escaping (CourseStructure) -> Void) -> Perform { - return Perform(method: .m_enrichCourseStructureWithLocalProgress__structure(`structure`), performs: perform) - } - public static func getCourseProgress(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseProgress__courseID_courseID(`courseID`), performs: perform) - } - public static func getCourseProgressOffline(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseProgressOffline__courseID_courseID(`courseID`), performs: perform) - } - public static func getAllVideosForNavigation(structure course: Parameter, perform: @escaping (CourseStructure) -> Void) -> Perform { - return Perform(method: .m_getAllVideosForNavigation__structure_course(`course`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CourseStructureManagerProtocol - -open class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getLoadedCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func shiftDueDates(courseID: String) throws { - addInvocation(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - do { - _ = try methodReturnValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - - fileprivate enum MethodType { - case m_getCourseBlocks__courseID_courseID(Parameter) - case m_getLoadedCourseBlocks__courseID_courseID(Parameter) - case m_shiftDueDates__courseID_courseID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseBlocks__courseID_courseID(let lhsCourseid), .m_getCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getLoadedCourseBlocks__courseID_courseID(let lhsCourseid), .m_getLoadedCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_shiftDueDates__courseID_courseID(let lhsCourseid), .m_shiftDueDates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_getLoadedCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_shiftDueDates__courseID_courseID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getCourseBlocks__courseID_courseID: return ".getCourseBlocks(courseID:)" - case .m_getLoadedCourseBlocks__courseID_courseID: return ".getLoadedCourseBlocks(courseID:)" - case .m_shiftDueDates__courseID_courseID: return ".shiftDueDates(courseID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getLoadedCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func shiftDueDates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func shiftDueDates(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseBlocks__courseID_courseID(`courseID`))} - public static func getLoadedCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`))} - public static func shiftDueDates(courseID: Parameter) -> Verify { return Verify(method: .m_shiftDueDates__courseID_courseID(`courseID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func getLoadedCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func shiftDueDates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_shiftDueDates__courseID_courseID(`courseID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DownloadManagerProtocol - -open class DownloadManagerProtocolMock: DownloadManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCurrentDownloadTask() -> DownloadDataTask? { - addInvocation(.m_getCurrentDownloadTask) - let perform = methodPerformValue(.m_getCurrentDownloadTask) as? () -> Void - perform?() - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_getCurrentDownloadTask).casted() - } catch { - // do nothing - } - return __value - } - - open func eventPublisher() -> AnyPublisher { - addInvocation(.m_eventPublisher) - let perform = methodPerformValue(.m_eventPublisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_eventPublisher).casted() - } catch { - onFatalFailure("Stub return value not specified for eventPublisher(). Use given") - Failure("Stub return value not specified for eventPublisher(). Use given") - } - return __value - } - - open func addToDownloadQueue(blocks: [CourseBlock]) throws { - addInvocation(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - do { - _ = try methodReturnValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getDownloadTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasks) - let perform = methodPerformValue(.m_getDownloadTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasks(). Use given") - Failure("Stub return value not specified for getDownloadTasks(). Use given") - } - return __value - } - - open func getDownloadTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func cancelDownloading(courseId: String, blocks: [CourseBlock]) throws { - addInvocation(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) as? (String, [CourseBlock]) -> Void - perform?(`courseId`, `blocks`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(task: DownloadDataTask) throws { - addInvocation(.m_cancelDownloading__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_cancelDownloading__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - do { - _ = try methodReturnValue(.m_cancelDownloading__task_task(Parameter.value(`task`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(courseId: String) throws { - addInvocation(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelAllDownloading() throws { - addInvocation(.m_cancelAllDownloading) - let perform = methodPerformValue(.m_cancelAllDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_cancelAllDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func deleteAll() { - addInvocation(.m_deleteAll) - let perform = methodPerformValue(.m_deleteAll) as? () -> Void - perform?() - } - - open func fileUrl(for blockId: String) -> URL? { - addInvocation(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: URL? = nil - do { - __value = try methodReturnValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func resumeDownloading() throws { - addInvocation(.m_resumeDownloading) - let perform = methodPerformValue(.m_resumeDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_resumeDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func isLargeVideosSize(blocks: [CourseBlock]) -> Bool { - addInvocation(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - Failure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - } - return __value - } - - open func removeAppSupportDirectoryUnusedContent() { - addInvocation(.m_removeAppSupportDirectoryUnusedContent) - let perform = methodPerformValue(.m_removeAppSupportDirectoryUnusedContent) as? () -> Void - perform?() - } - - open func delete(blocks: [CourseBlock], courseId: String) { - addInvocation(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) as? ([CourseBlock], String) -> Void - perform?(`blocks`, `courseId`) - } - - open func downloadTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getFreeDiskSpace() -> Int? { - addInvocation(.m_getFreeDiskSpace) - let perform = methodPerformValue(.m_getFreeDiskSpace) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getFreeDiskSpace).casted() - } catch { - // do nothing - } - return __value - } - - - fileprivate enum MethodType { - case m_getCurrentDownloadTask - case m_eventPublisher - case m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>) - case m_getDownloadTasks - case m_getDownloadTasksForCourse__courseId(Parameter) - case m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter, Parameter<[CourseBlock]>) - case m_cancelDownloading__task_task(Parameter) - case m_cancelDownloading__courseId_courseId(Parameter) - case m_cancelAllDownloading - case m_deleteAll - case m_fileUrl__for_blockId(Parameter) - case m_resumeDownloading - case m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>) - case m_removeAppSupportDirectoryUnusedContent - case m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>, Parameter) - case m_downloadTask__for_blockId(Parameter) - case m_getFreeDiskSpace - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCurrentDownloadTask, .m_getCurrentDownloadTask): return .match - - case (.m_eventPublisher, .m_eventPublisher): return .match - - case (.m_addToDownloadQueue__blocks_blocks(let lhsBlocks), .m_addToDownloadQueue__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadTasks, .m_getDownloadTasks): return .match - - case (.m_getDownloadTasksForCourse__courseId(let lhsCourseid), .m_getDownloadTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseIdblocks_blocks(let lhsCourseid, let lhsBlocks), .m_cancelDownloading__courseId_courseIdblocks_blocks(let rhsCourseid, let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__task_task(let lhsTask), .m_cancelDownloading__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseId(let lhsCourseid), .m_cancelDownloading__courseId_courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelAllDownloading, .m_cancelAllDownloading): return .match - - case (.m_deleteAll, .m_deleteAll): return .match - - case (.m_fileUrl__for_blockId(let lhsBlockid), .m_fileUrl__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_resumeDownloading, .m_resumeDownloading): return .match - - case (.m_isLargeVideosSize__blocks_blocks(let lhsBlocks), .m_isLargeVideosSize__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_removeAppSupportDirectoryUnusedContent, .m_removeAppSupportDirectoryUnusedContent): return .match - - case (.m_delete__blocks_blockscourseId_courseId(let lhsBlocks, let lhsCourseid), .m_delete__blocks_blockscourseId_courseId(let rhsBlocks, let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_downloadTask__for_blockId(let lhsBlockid), .m_downloadTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getFreeDiskSpace, .m_getFreeDiskSpace): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_getCurrentDownloadTask: return 0 - case .m_eventPublisher: return 0 - case let .m_addToDownloadQueue__blocks_blocks(p0): return p0.intValue - case .m_getDownloadTasks: return 0 - case let .m_getDownloadTasksForCourse__courseId(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseIdblocks_blocks(p0, p1): return p0.intValue + p1.intValue - case let .m_cancelDownloading__task_task(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseId(p0): return p0.intValue - case .m_cancelAllDownloading: return 0 - case .m_deleteAll: return 0 - case let .m_fileUrl__for_blockId(p0): return p0.intValue - case .m_resumeDownloading: return 0 - case let .m_isLargeVideosSize__blocks_blocks(p0): return p0.intValue - case .m_removeAppSupportDirectoryUnusedContent: return 0 - case let .m_delete__blocks_blockscourseId_courseId(p0, p1): return p0.intValue + p1.intValue - case let .m_downloadTask__for_blockId(p0): return p0.intValue - case .m_getFreeDiskSpace: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_getCurrentDownloadTask: return ".getCurrentDownloadTask()" - case .m_eventPublisher: return ".eventPublisher()" - case .m_addToDownloadQueue__blocks_blocks: return ".addToDownloadQueue(blocks:)" - case .m_getDownloadTasks: return ".getDownloadTasks()" - case .m_getDownloadTasksForCourse__courseId: return ".getDownloadTasksForCourse(_:)" - case .m_cancelDownloading__courseId_courseIdblocks_blocks: return ".cancelDownloading(courseId:blocks:)" - case .m_cancelDownloading__task_task: return ".cancelDownloading(task:)" - case .m_cancelDownloading__courseId_courseId: return ".cancelDownloading(courseId:)" - case .m_cancelAllDownloading: return ".cancelAllDownloading()" - case .m_deleteAll: return ".deleteAll()" - case .m_fileUrl__for_blockId: return ".fileUrl(for:)" - case .m_resumeDownloading: return ".resumeDownloading()" - case .m_isLargeVideosSize__blocks_blocks: return ".isLargeVideosSize(blocks:)" - case .m_removeAppSupportDirectoryUnusedContent: return ".removeAppSupportDirectoryUnusedContent()" - case .m_delete__blocks_blockscourseId_courseId: return ".delete(blocks:courseId:)" - case .m_downloadTask__for_blockId: return ".downloadTask(for:)" - case .m_getFreeDiskSpace: return ".getFreeDiskSpace()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCurrentDownloadTask(willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func eventPublisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func fileUrl(for blockId: Parameter, willReturn: URL?...) -> MethodStub { - return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getFreeDiskSpace(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCurrentDownloadTask(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func eventPublisher(willProduce: (Stubber>) -> Void) -> MethodStub { - let willReturn: [AnyPublisher] = [] - let given: Given = { return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - public static func getDownloadTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func fileUrl(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [URL?] = [] - let given: Given = { return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (URL?).self) - willProduce(stubber) - return given - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func downloadTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getFreeDiskSpace(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(task: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(task: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelAllDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelAllDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func resumeDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resumeDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCurrentDownloadTask() -> Verify { return Verify(method: .m_getCurrentDownloadTask)} - public static func eventPublisher() -> Verify { return Verify(method: .m_eventPublisher)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocks(`blocks`))} - public static func getDownloadTasks() -> Verify { return Verify(method: .m_getDownloadTasks)} - public static func getDownloadTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadTasksForCourse__courseId(`courseId`))} - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`))} - public static func cancelDownloading(task: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__task_task(`task`))} - public static func cancelDownloading(courseId: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseId(`courseId`))} - public static func cancelAllDownloading() -> Verify { return Verify(method: .m_cancelAllDownloading)} - public static func deleteAll() -> Verify { return Verify(method: .m_deleteAll)} - public static func fileUrl(for blockId: Parameter) -> Verify { return Verify(method: .m_fileUrl__for_blockId(`blockId`))} - public static func resumeDownloading() -> Verify { return Verify(method: .m_resumeDownloading)} - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_isLargeVideosSize__blocks_blocks(`blocks`))} - public static func removeAppSupportDirectoryUnusedContent() -> Verify { return Verify(method: .m_removeAppSupportDirectoryUnusedContent)} - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter) -> Verify { return Verify(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`))} - public static func downloadTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadTask__for_blockId(`blockId`))} - public static func getFreeDiskSpace() -> Verify { return Verify(method: .m_getFreeDiskSpace)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCurrentDownloadTask(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getCurrentDownloadTask, performs: perform) - } - public static func eventPublisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_eventPublisher, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), performs: perform) - } - public static func getDownloadTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadTasks, performs: perform) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, perform: @escaping (String, [CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), performs: perform) - } - public static func cancelDownloading(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__task_task(`task`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseId(`courseId`), performs: perform) - } - public static func cancelAllDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_cancelAllDownloading, performs: perform) - } - public static func deleteAll(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAll, performs: perform) - } - public static func fileUrl(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_fileUrl__for_blockId(`blockId`), performs: perform) - } - public static func resumeDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_resumeDownloading, performs: perform) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), performs: perform) - } - public static func removeAppSupportDirectoryUnusedContent(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeAppSupportDirectoryUnusedContent, performs: perform) - } - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter, perform: @escaping ([CourseBlock], String) -> Void) -> Perform { - return Perform(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`), performs: perform) - } - public static func downloadTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadTask__for_blockId(`blockId`), performs: perform) - } - public static func getFreeDiskSpace(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getFreeDiskSpace, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - OfflineSyncInteractorProtocol - -open class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func submitOfflineProgress(courseID: String, blockID: String, data: String) throws -> Bool { - addInvocation(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) - let perform = methodPerformValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) as? (String, String, String) -> Void - perform?(`courseID`, `blockID`, `data`) - var __value: Bool - do { - __value = try methodReturnValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - Failure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter, Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let lhsCourseid, let lhsBlockid, let lhsData), .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let rhsCourseid, let rhsBlockid, let rhsData)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsData, rhs: rhsData, with: matcher), lhsData, rhsData, "data")) - return Matcher.ComparisonResult(results) - } - } - - func intValue() -> Int { - switch self { - case let .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data: return ".submitOfflineProgress(courseID:blockID:data:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter) -> Verify { return Verify(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - diff --git a/Course/CourseTests/Generated/CourseMocks.generated.swift b/Course/CourseTests/Generated/CourseMocks.generated.swift new file mode 100644 index 000000000..1fdb4fc3e --- /dev/null +++ b/Course/CourseTests/Generated/CourseMocks.generated.swift @@ -0,0 +1,4200 @@ +/// +/// @Generated by Mockolo +/// + + + +import AVKit +import Alamofire +import Combine +@testable import Core +import CoreData +@testable import Course +import Foundation +import OEXFoundation +import SwiftUI +import ZipArchive + + +public final class ConfigProtocolMock: ConfigProtocol, @unchecked Sendable { + public init() { } + public init(baseURL: URL = URL(fileURLWithPath: ""), baseSSOURL: URL = URL(fileURLWithPath: ""), ssoFinishedURL: URL = URL(fileURLWithPath: ""), ssoButtonTitle: [String: Any] = [String: Any](), oAuthClientId: String = "", tokenType: TokenType, feedbackEmail: String = "", appStoreLink: String = "", faq: URL? = nil, platformName: String = "", agreement: AgreementConfig, firebase: FirebaseConfig, facebook: FacebookConfig, microsoft: MicrosoftConfig, google: GoogleConfig, appleSignIn: AppleSignInConfig, features: FeaturesConfig, theme: ThemeConfig, uiComponents: UIComponentsConfig, discovery: DiscoveryConfig, dashboard: DashboardConfig, braze: BrazeConfig, branch: BranchConfig, program: DiscoveryConfig, experimentalFeatures: ExperimentalFeaturesConfig, URIScheme: String = "") { + self.baseURL = baseURL + self.baseSSOURL = baseSSOURL + self.ssoFinishedURL = ssoFinishedURL + self.ssoButtonTitle = ssoButtonTitle + self.oAuthClientId = oAuthClientId + self._tokenType = tokenType + self.feedbackEmail = feedbackEmail + self.appStoreLink = appStoreLink + self.faq = faq + self.platformName = platformName + self._agreement = agreement + self._firebase = firebase + self._facebook = facebook + self._microsoft = microsoft + self._google = google + self._appleSignIn = appleSignIn + self._features = features + self._theme = theme + self._uiComponents = uiComponents + self._discovery = discovery + self._dashboard = dashboard + self._braze = braze + self._branch = branch + self._program = program + self._experimentalFeatures = experimentalFeatures + self.URIScheme = URIScheme + } + + + + public var baseURL: URL = URL(fileURLWithPath: "") + + + public var baseSSOURL: URL = URL(fileURLWithPath: "") + + + public var ssoFinishedURL: URL = URL(fileURLWithPath: "") + + + public var ssoButtonTitle: [String: Any] = [String: Any]() + + + public var oAuthClientId: String = "" + + + private var _tokenType: TokenType! + public var tokenType: TokenType { + get { return _tokenType } + set { _tokenType = newValue } + } + + + public var feedbackEmail: String = "" + + + public var appStoreLink: String = "" + + + public var faq: URL? = nil + + + public var platformName: String = "" + + + private var _agreement: AgreementConfig! + public var agreement: AgreementConfig { + get { return _agreement } + set { _agreement = newValue } + } + + + private var _firebase: FirebaseConfig! + public var firebase: FirebaseConfig { + get { return _firebase } + set { _firebase = newValue } + } + + + private var _facebook: FacebookConfig! + public var facebook: FacebookConfig { + get { return _facebook } + set { _facebook = newValue } + } + + + private var _microsoft: MicrosoftConfig! + public var microsoft: MicrosoftConfig { + get { return _microsoft } + set { _microsoft = newValue } + } + + + private var _google: GoogleConfig! + public var google: GoogleConfig { + get { return _google } + set { _google = newValue } + } + + + private var _appleSignIn: AppleSignInConfig! + public var appleSignIn: AppleSignInConfig { + get { return _appleSignIn } + set { _appleSignIn = newValue } + } + + + private var _features: FeaturesConfig! + public var features: FeaturesConfig { + get { return _features } + set { _features = newValue } + } + + + private var _theme: ThemeConfig! + public var theme: ThemeConfig { + get { return _theme } + set { _theme = newValue } + } + + + private var _uiComponents: UIComponentsConfig! + public var uiComponents: UIComponentsConfig { + get { return _uiComponents } + set { _uiComponents = newValue } + } + + + private var _discovery: DiscoveryConfig! + public var discovery: DiscoveryConfig { + get { return _discovery } + set { _discovery = newValue } + } + + + private var _dashboard: DashboardConfig! + public var dashboard: DashboardConfig { + get { return _dashboard } + set { _dashboard = newValue } + } + + + private var _braze: BrazeConfig! + public var braze: BrazeConfig { + get { return _braze } + set { _braze = newValue } + } + + + private var _branch: BranchConfig! + public var branch: BranchConfig { + get { return _branch } + set { _branch = newValue } + } + + + private var _program: DiscoveryConfig! + public var program: DiscoveryConfig { + get { return _program } + set { _program = newValue } + } + + + private var _experimentalFeatures: ExperimentalFeaturesConfig! + public var experimentalFeatures: ExperimentalFeaturesConfig { + get { return _experimentalFeatures } + set { _experimentalFeatures = newValue } + } + + + public var URIScheme: String = "" +} + +public final class CoreAnalyticsMock: CoreAnalytics { + public init() { } + + + public private(set) var trackEventCallCount = 0 + public var trackEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackEventCallCount += 1 + if let trackEventHandler = trackEventHandler { + trackEventHandler(event, parameters) + } + + } + + public private(set) var trackEventBiValueCallCount = 0 + public var trackEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackEventBiValueCallCount += 1 + if let trackEventBiValueHandler = trackEventBiValueHandler { + trackEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var trackScreenEventCallCount = 0 + public var trackScreenEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackScreenEventCallCount += 1 + if let trackScreenEventHandler = trackScreenEventHandler { + trackScreenEventHandler(event, parameters) + } + + } + + public private(set) var trackScreenEventBiValueCallCount = 0 + public var trackScreenEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackScreenEventBiValueCallCount += 1 + if let trackScreenEventBiValueHandler = trackScreenEventBiValueHandler { + trackScreenEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var appreviewCallCount = 0 + public var appreviewHandler: ((AnalyticsEvent, EventBIValue, String?, Int?) -> ())? + public func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { + appreviewCallCount += 1 + if let appreviewHandler = appreviewHandler { + appreviewHandler(event, biValue, action, rating) + } + + } + + public private(set) var videoQualityChangedCallCount = 0 + public var videoQualityChangedHandler: ((AnalyticsEvent, EventBIValue, String, String) -> ())? + public func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { + videoQualityChangedCallCount += 1 + if let videoQualityChangedHandler = videoQualityChangedHandler { + videoQualityChangedHandler(event, bivalue, value, oldValue) + } + + } +} + +public final class CoreStorageMock: CoreStorage, @unchecked Sendable { + public init() { } + public init(accessToken: String? = nil, refreshToken: String? = nil, pushToken: String? = nil, appleSignFullName: String? = nil, appleSignEmail: String? = nil, cookiesDate: Date? = nil, reviewLastShownVersion: String? = nil, lastReviewDate: Date? = nil, user: DataLayer.User? = nil, userSettings: UserSettings? = nil, resetAppSupportDirectoryUserData: Bool? = nil, useRelativeDates: Bool = false, lastUsedSocialAuth: String? = nil, latestAvailableAppVersion: String? = nil, updateAppRequired: Bool = false) { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.pushToken = pushToken + self.appleSignFullName = appleSignFullName + self.appleSignEmail = appleSignEmail + self.cookiesDate = cookiesDate + self.reviewLastShownVersion = reviewLastShownVersion + self.lastReviewDate = lastReviewDate + self.user = user + self.userSettings = userSettings + self.resetAppSupportDirectoryUserData = resetAppSupportDirectoryUserData + self.useRelativeDates = useRelativeDates + self.lastUsedSocialAuth = lastUsedSocialAuth + self.latestAvailableAppVersion = latestAvailableAppVersion + self.updateAppRequired = updateAppRequired + } + + + public private(set) var accessTokenSetCallCount = 0 + public var accessToken: String? = nil { didSet { accessTokenSetCallCount += 1 } } + + public private(set) var refreshTokenSetCallCount = 0 + public var refreshToken: String? = nil { didSet { refreshTokenSetCallCount += 1 } } + + public private(set) var pushTokenSetCallCount = 0 + public var pushToken: String? = nil { didSet { pushTokenSetCallCount += 1 } } + + public private(set) var appleSignFullNameSetCallCount = 0 + public var appleSignFullName: String? = nil { didSet { appleSignFullNameSetCallCount += 1 } } + + public private(set) var appleSignEmailSetCallCount = 0 + public var appleSignEmail: String? = nil { didSet { appleSignEmailSetCallCount += 1 } } + + public private(set) var cookiesDateSetCallCount = 0 + public var cookiesDate: Date? = nil { didSet { cookiesDateSetCallCount += 1 } } + + public private(set) var reviewLastShownVersionSetCallCount = 0 + public var reviewLastShownVersion: String? = nil { didSet { reviewLastShownVersionSetCallCount += 1 } } + + public private(set) var lastReviewDateSetCallCount = 0 + public var lastReviewDate: Date? = nil { didSet { lastReviewDateSetCallCount += 1 } } + + public private(set) var userSetCallCount = 0 + public var user: DataLayer.User? = nil { didSet { userSetCallCount += 1 } } + + public private(set) var userSettingsSetCallCount = 0 + public var userSettings: UserSettings? = nil { didSet { userSettingsSetCallCount += 1 } } + + public private(set) var resetAppSupportDirectoryUserDataSetCallCount = 0 + public var resetAppSupportDirectoryUserData: Bool? = nil { didSet { resetAppSupportDirectoryUserDataSetCallCount += 1 } } + + public private(set) var useRelativeDatesSetCallCount = 0 + public var useRelativeDates: Bool = false { didSet { useRelativeDatesSetCallCount += 1 } } + + public private(set) var lastUsedSocialAuthSetCallCount = 0 + public var lastUsedSocialAuth: String? = nil { didSet { lastUsedSocialAuthSetCallCount += 1 } } + + public private(set) var latestAvailableAppVersionSetCallCount = 0 + public var latestAvailableAppVersion: String? = nil { didSet { latestAvailableAppVersionSetCallCount += 1 } } + + public private(set) var updateAppRequiredSetCallCount = 0 + public var updateAppRequired: Bool = false { didSet { updateAppRequiredSetCallCount += 1 } } + + private let clearState = MockoloMutex(MockoloHandlerState ()>()) + public var clearCallCount: Int { + return clearState.withLock(\.callCount) + } + public var clearHandler: (@Sendable () -> ())? { + get { clearState.withLock(\.handler) } + set { clearState.withLock { $0.handler = newValue } } + } + public func clear() { + let clearHandler = clearState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearHandler = clearHandler { + clearHandler() + } + + } +} + +public final class AuthInteractorProtocolMock: AuthInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let loginState = MockoloMutex(MockoloHandlerState User>()) + public var loginCallCount: Int { + return loginState.withLock(\.callCount) + } + public var loginHandler: (@Sendable (String, String) async throws -> User)? { + get { loginState.withLock(\.handler) } + set { loginState.withLock { $0.handler = newValue } } + } + public func login(username: String, password: String) async throws -> User { + let loginHandler = loginState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginHandler = loginHandler { + return try await loginHandler(username, password) + } + fatalError("loginHandler returns can't have a default value thus its handler must be set") + } + + private let loginExternalTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginExternalTokenCallCount: Int { + return loginExternalTokenState.withLock(\.callCount) + } + public var loginExternalTokenHandler: (@Sendable (String, String) async throws -> User)? { + get { loginExternalTokenState.withLock(\.handler) } + set { loginExternalTokenState.withLock { $0.handler = newValue } } + } + public func login(externalToken: String, backend: String) async throws -> User { + let loginExternalTokenHandler = loginExternalTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginExternalTokenHandler = loginExternalTokenHandler { + return try await loginExternalTokenHandler(externalToken, backend) + } + fatalError("loginExternalTokenHandler returns can't have a default value thus its handler must be set") + } + + private let loginSsoTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginSsoTokenCallCount: Int { + return loginSsoTokenState.withLock(\.callCount) + } + public var loginSsoTokenHandler: (@Sendable (String) async throws -> User)? { + get { loginSsoTokenState.withLock(\.handler) } + set { loginSsoTokenState.withLock { $0.handler = newValue } } + } + public func login(ssoToken: String) async throws -> User { + let loginSsoTokenHandler = loginSsoTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginSsoTokenHandler = loginSsoTokenHandler { + return try await loginSsoTokenHandler(ssoToken) + } + fatalError("loginSsoTokenHandler returns can't have a default value thus its handler must be set") + } + + private let resetPasswordState = MockoloMutex(MockoloHandlerState ResetPassword>()) + public var resetPasswordCallCount: Int { + return resetPasswordState.withLock(\.callCount) + } + public var resetPasswordHandler: (@Sendable (String) async throws -> ResetPassword)? { + get { resetPasswordState.withLock(\.handler) } + set { resetPasswordState.withLock { $0.handler = newValue } } + } + public func resetPassword(email: String) async throws -> ResetPassword { + let resetPasswordHandler = resetPasswordState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resetPasswordHandler = resetPasswordHandler { + return try await resetPasswordHandler(email) + } + fatalError("resetPasswordHandler returns can't have a default value thus its handler must be set") + } + + private let getCookiesState = MockoloMutex(MockoloHandlerState ()>()) + public var getCookiesCallCount: Int { + return getCookiesState.withLock(\.callCount) + } + public var getCookiesHandler: (@Sendable (Bool) async throws -> ())? { + get { getCookiesState.withLock(\.handler) } + set { getCookiesState.withLock { $0.handler = newValue } } + } + public func getCookies(force: Bool) async throws { + let getCookiesHandler = getCookiesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCookiesHandler = getCookiesHandler { + try await getCookiesHandler(force) + } + + } + + private let getRegistrationFieldsState = MockoloMutex(MockoloHandlerState [PickerFields]>()) + public var getRegistrationFieldsCallCount: Int { + return getRegistrationFieldsState.withLock(\.callCount) + } + public var getRegistrationFieldsHandler: (@Sendable () async throws -> [PickerFields])? { + get { getRegistrationFieldsState.withLock(\.handler) } + set { getRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func getRegistrationFields() async throws -> [PickerFields] { + let getRegistrationFieldsHandler = getRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getRegistrationFieldsHandler = getRegistrationFieldsHandler { + return try await getRegistrationFieldsHandler() + } + return [PickerFields]() + } + + private let registerUserState = MockoloMutex(MockoloHandlerState User>()) + public var registerUserCallCount: Int { + return registerUserState.withLock(\.callCount) + } + public var registerUserHandler: (@Sendable ([String: String], Bool) async throws -> User)? { + get { registerUserState.withLock(\.handler) } + set { registerUserState.withLock { $0.handler = newValue } } + } + public func registerUser(fields: [String: String], isSocial: Bool) async throws -> User { + let registerUserHandler = registerUserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let registerUserHandler = registerUserHandler { + return try await registerUserHandler(fields, isSocial) + } + fatalError("registerUserHandler returns can't have a default value thus its handler must be set") + } + + private let validateRegistrationFieldsState = MockoloMutex(MockoloHandlerState [String: String]>()) + public var validateRegistrationFieldsCallCount: Int { + return validateRegistrationFieldsState.withLock(\.callCount) + } + public var validateRegistrationFieldsHandler: (@Sendable ([String: String]) async throws -> [String: String])? { + get { validateRegistrationFieldsState.withLock(\.handler) } + set { validateRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func validateRegistrationFields(fields: [String: String]) async throws -> [String: String] { + let validateRegistrationFieldsHandler = validateRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let validateRegistrationFieldsHandler = validateRegistrationFieldsHandler { + return try await validateRegistrationFieldsHandler(fields) + } + return [String: String]() + } +} + +public final class PlayerServiceProtocolMock: PlayerServiceProtocol, @unchecked Sendable { + private var _blockID: String! + private var _courseID: String! + private var _interactor: CourseInteractorProtocol! + public init() { } + public init(router: CourseRouter) { + self._router = router + } + required public init(courseID: String = "", blockID: String = "", interactor: CourseInteractorProtocol = CourseInteractorProtocolMock(), router: CourseRouter) { + self._courseID = courseID + self._blockID = blockID + self._interactor = interactor + self._router = router + } + + + + private var _router: CourseRouter! + public var router: CourseRouter { + get { return _router } + set { _router = newValue } + } + + private let blockCompletionRequestState = MockoloMutex(MockoloHandlerState ()>()) + public var blockCompletionRequestCallCount: Int { + return blockCompletionRequestState.withLock(\.callCount) + } + public var blockCompletionRequestHandler: (@Sendable () async throws -> ())? { + get { blockCompletionRequestState.withLock(\.handler) } + set { blockCompletionRequestState.withLock { $0.handler = newValue } } + } + public func blockCompletionRequest() async throws { + let blockCompletionRequestHandler = blockCompletionRequestState.withLock { state in + state.callCount += 1 + return state.handler + } + if let blockCompletionRequestHandler = blockCompletionRequestHandler { + try await blockCompletionRequestHandler() + } + + } + + private let presentAppReviewState = MockoloMutex(MockoloHandlerState ()>()) + public var presentAppReviewCallCount: Int { + return presentAppReviewState.withLock(\.callCount) + } + public var presentAppReviewHandler: (@Sendable () -> ())? { + get { presentAppReviewState.withLock(\.handler) } + set { presentAppReviewState.withLock { $0.handler = newValue } } + } + public func presentAppReview() { + let presentAppReviewHandler = presentAppReviewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAppReviewHandler = presentAppReviewHandler { + presentAppReviewHandler() + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, Bool, @MainActor () -> any View) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: @MainActor () -> any View) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, animated, content) + } + + } + + private let getSubtitlesState = MockoloMutex(MockoloHandlerState [Subtitle]>()) + public var getSubtitlesCallCount: Int { + return getSubtitlesState.withLock(\.callCount) + } + public var getSubtitlesHandler: (@Sendable (String, String) async throws -> [Subtitle])? { + get { getSubtitlesState.withLock(\.handler) } + set { getSubtitlesState.withLock { $0.handler = newValue } } + } + public func getSubtitles(url: String, selectedLanguage: String) async throws -> [Subtitle] { + let getSubtitlesHandler = getSubtitlesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getSubtitlesHandler = getSubtitlesHandler { + return try await getSubtitlesHandler(url, selectedLanguage) + } + return [Subtitle]() + } + + private let updateVideoProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var updateVideoProgressCallCount: Int { + return updateVideoProgressState.withLock(\.callCount) + } + public var updateVideoProgressHandler: (@Sendable (Double) async -> ())? { + get { updateVideoProgressState.withLock(\.handler) } + set { updateVideoProgressState.withLock { $0.handler = newValue } } + } + public func updateVideoProgress(progress: Double) async { + let updateVideoProgressHandler = updateVideoProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateVideoProgressHandler = updateVideoProgressHandler { + await updateVideoProgressHandler(progress) + } + + } + + private let loadVideoProgressState = MockoloMutex(MockoloHandlerState Double?>()) + public var loadVideoProgressCallCount: Int { + return loadVideoProgressState.withLock(\.callCount) + } + public var loadVideoProgressHandler: (@Sendable () async -> Double?)? { + get { loadVideoProgressState.withLock(\.handler) } + set { loadVideoProgressState.withLock { $0.handler = newValue } } + } + public func loadVideoProgress() async -> Double? { + let loadVideoProgressHandler = loadVideoProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadVideoProgressHandler = loadVideoProgressHandler { + return await loadVideoProgressHandler() + } + return nil + } +} + +public final class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let submitOfflineProgressState = MockoloMutex(MockoloHandlerState Bool>()) + public var submitOfflineProgressCallCount: Int { + return submitOfflineProgressState.withLock(\.callCount) + } + public var submitOfflineProgressHandler: (@Sendable (String, String, String) async throws -> Bool)? { + get { submitOfflineProgressState.withLock(\.handler) } + set { submitOfflineProgressState.withLock { $0.handler = newValue } } + } + public func submitOfflineProgress(courseID: String, blockID: String, data: String) async throws -> Bool { + let submitOfflineProgressHandler = submitOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let submitOfflineProgressHandler = submitOfflineProgressHandler { + return try await submitOfflineProgressHandler(courseID, blockID, data) + } + return false + } +} + +public final class WebviewCookiesUpdateProtocolMock: WebviewCookiesUpdateProtocol { + public init() { } + public init(authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock(), cookiesReady: Bool = false, updatingCookies: Bool = false, errorMessage: String? = nil) { + self.authInteractor = authInteractor + self.cookiesReady = cookiesReady + self.updatingCookies = updatingCookies + self.errorMessage = errorMessage + } + + + + public var authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock() + + public private(set) var cookiesReadySetCallCount = 0 + public var cookiesReady: Bool = false { didSet { cookiesReadySetCallCount += 1 } } + + public private(set) var updatingCookiesSetCallCount = 0 + public var updatingCookies: Bool = false { didSet { updatingCookiesSetCallCount += 1 } } + + public private(set) var errorMessageSetCallCount = 0 + public var errorMessage: String? = nil { didSet { errorMessageSetCallCount += 1 } } + + public private(set) var updateCookiesCallCount = 0 + public var updateCookiesHandler: ((Bool, Int) async -> ())? + public func updateCookies(force: Bool, retryCount: Int) async { + updateCookiesCallCount += 1 + if let updateCookiesHandler = updateCookiesHandler { + await updateCookiesHandler(force, retryCount) + } + + } +} + +public final class BaseRouterMock: BaseRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class CalendarManagerProtocolMock: CalendarManagerProtocol, @unchecked Sendable { + public init() { } + + + private let createCalendarIfNeededState = MockoloMutex(MockoloHandlerState ()>()) + public var createCalendarIfNeededCallCount: Int { + return createCalendarIfNeededState.withLock(\.callCount) + } + public var createCalendarIfNeededHandler: (@Sendable () -> ())? { + get { createCalendarIfNeededState.withLock(\.handler) } + set { createCalendarIfNeededState.withLock { $0.handler = newValue } } + } + public func createCalendarIfNeeded() { + let createCalendarIfNeededHandler = createCalendarIfNeededState.withLock { state in + state.callCount += 1 + return state.handler + } + if let createCalendarIfNeededHandler = createCalendarIfNeededHandler { + createCalendarIfNeededHandler() + } + + } + + private let filterCoursesBySelectedState = MockoloMutex(MockoloHandlerState [CourseForSync]>()) + public var filterCoursesBySelectedCallCount: Int { + return filterCoursesBySelectedState.withLock(\.callCount) + } + public var filterCoursesBySelectedHandler: (@Sendable ([CourseForSync]) async -> [CourseForSync])? { + get { filterCoursesBySelectedState.withLock(\.handler) } + set { filterCoursesBySelectedState.withLock { $0.handler = newValue } } + } + public func filterCoursesBySelected(fetchedCourses: [CourseForSync]) async -> [CourseForSync] { + let filterCoursesBySelectedHandler = filterCoursesBySelectedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let filterCoursesBySelectedHandler = filterCoursesBySelectedHandler { + return await filterCoursesBySelectedHandler(fetchedCourses) + } + return [CourseForSync]() + } + + private let removeOldCalendarState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOldCalendarCallCount: Int { + return removeOldCalendarState.withLock(\.callCount) + } + public var removeOldCalendarHandler: (@Sendable () -> ())? { + get { removeOldCalendarState.withLock(\.handler) } + set { removeOldCalendarState.withLock { $0.handler = newValue } } + } + public func removeOldCalendar() { + let removeOldCalendarHandler = removeOldCalendarState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOldCalendarHandler = removeOldCalendarHandler { + removeOldCalendarHandler() + } + + } + + private let removeOutdatedEventsState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOutdatedEventsCallCount: Int { + return removeOutdatedEventsState.withLock(\.callCount) + } + public var removeOutdatedEventsHandler: (@Sendable (String) async -> ())? { + get { removeOutdatedEventsState.withLock(\.handler) } + set { removeOutdatedEventsState.withLock { $0.handler = newValue } } + } + public func removeOutdatedEvents(courseID: String) async { + let removeOutdatedEventsHandler = removeOutdatedEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOutdatedEventsHandler = removeOutdatedEventsHandler { + await removeOutdatedEventsHandler(courseID) + } + + } + + private let syncCourseState = MockoloMutex(MockoloHandlerState ()>()) + public var syncCourseCallCount: Int { + return syncCourseState.withLock(\.callCount) + } + public var syncCourseHandler: (@Sendable (String, String, CourseDates) async -> ())? { + get { syncCourseState.withLock(\.handler) } + set { syncCourseState.withLock { $0.handler = newValue } } + } + public func syncCourse(courseID: String, courseName: String, dates: CourseDates) async { + let syncCourseHandler = syncCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let syncCourseHandler = syncCourseHandler { + await syncCourseHandler(courseID, courseName, dates) + } + + } + + private let requestAccessState = MockoloMutex(MockoloHandlerState Bool>()) + public var requestAccessCallCount: Int { + return requestAccessState.withLock(\.callCount) + } + public var requestAccessHandler: (@Sendable () async -> Bool)? { + get { requestAccessState.withLock(\.handler) } + set { requestAccessState.withLock { $0.handler = newValue } } + } + public func requestAccess() async -> Bool { + let requestAccessHandler = requestAccessState.withLock { state in + state.callCount += 1 + return state.handler + } + if let requestAccessHandler = requestAccessHandler { + return await requestAccessHandler() + } + return false + } + + private let courseStatusState = MockoloMutex(MockoloHandlerState SyncStatus>()) + public var courseStatusCallCount: Int { + return courseStatusState.withLock(\.callCount) + } + public var courseStatusHandler: (@Sendable (String) async -> SyncStatus)? { + get { courseStatusState.withLock(\.handler) } + set { courseStatusState.withLock { $0.handler = newValue } } + } + public func courseStatus(courseID: String) async -> SyncStatus { + let courseStatusHandler = courseStatusState.withLock { state in + state.callCount += 1 + return state.handler + } + if let courseStatusHandler = courseStatusHandler { + return await courseStatusHandler(courseID) + } + fatalError("courseStatusHandler returns can't have a default value thus its handler must be set") + } + + private let clearAllDataState = MockoloMutex(MockoloHandlerState ()>()) + public var clearAllDataCallCount: Int { + return clearAllDataState.withLock(\.callCount) + } + public var clearAllDataHandler: (@Sendable (Bool) async -> ())? { + get { clearAllDataState.withLock(\.handler) } + set { clearAllDataState.withLock { $0.handler = newValue } } + } + public func clearAllData(removeCalendar: Bool) async { + let clearAllDataHandler = clearAllDataState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearAllDataHandler = clearAllDataHandler { + await clearAllDataHandler(removeCalendar) + } + + } + + private let isDatesChangedState = MockoloMutex(MockoloHandlerState Bool>()) + public var isDatesChangedCallCount: Int { + return isDatesChangedState.withLock(\.callCount) + } + public var isDatesChangedHandler: (@Sendable (String, String) async -> Bool)? { + get { isDatesChangedState.withLock(\.handler) } + set { isDatesChangedState.withLock { $0.handler = newValue } } + } + public func isDatesChanged(courseID: String, checksum: String) async -> Bool { + let isDatesChangedHandler = isDatesChangedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isDatesChangedHandler = isDatesChangedHandler { + return await isDatesChangedHandler(courseID, checksum) + } + return false + } +} + +public final class CourseRouterMock: CourseRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let presentAppReviewState = MockoloMutex(MockoloHandlerState ()>()) + public var presentAppReviewCallCount: Int { + return presentAppReviewState.withLock(\.callCount) + } + public var presentAppReviewHandler: (@Sendable () -> ())? { + get { presentAppReviewState.withLock(\.handler) } + set { presentAppReviewState.withLock { $0.handler = newValue } } + } + public func presentAppReview() { + let presentAppReviewHandler = presentAppReviewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAppReviewHandler = presentAppReviewHandler { + presentAppReviewHandler() + } + + } + + private let showCourseUnitState = MockoloMutex(MockoloHandlerState ()>()) + public var showCourseUnitCallCount: Int { + return showCourseUnitState.withLock(\.callCount) + } + public var showCourseUnitHandler: (@Sendable (String, String, String, Int, [CourseChapter], Int, Int, Bool, CourseStructure?) -> ())? { + get { showCourseUnitState.withLock(\.handler) } + set { showCourseUnitState.withLock { $0.handler = newValue } } + } + public func showCourseUnit(courseName: String, blockId: String, courseID: String, verticalIndex: Int, chapters: [CourseChapter], chapterIndex: Int, sequentialIndex: Int, showVideoNavigation: Bool, courseVideoStructure: CourseStructure?) { + let showCourseUnitHandler = showCourseUnitState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showCourseUnitHandler = showCourseUnitHandler { + showCourseUnitHandler(courseName, blockId, courseID, verticalIndex, chapters, chapterIndex, sequentialIndex, showVideoNavigation, courseVideoStructure) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let replaceCourseUnitState = MockoloMutex(MockoloHandlerState ()>()) + public var replaceCourseUnitCallCount: Int { + return replaceCourseUnitState.withLock(\.callCount) + } + public var replaceCourseUnitHandler: (@Sendable (String, String, String, Int, [CourseChapter], Int, Int, Bool, Bool, CourseStructure?) -> ())? { + get { replaceCourseUnitState.withLock(\.handler) } + set { replaceCourseUnitState.withLock { $0.handler = newValue } } + } + public func replaceCourseUnit(courseName: String, blockId: String, courseID: String, verticalIndex: Int, chapters: [CourseChapter], chapterIndex: Int, sequentialIndex: Int, animated: Bool, showVideoNavigation: Bool, courseVideoStructure: CourseStructure?) { + let replaceCourseUnitHandler = replaceCourseUnitState.withLock { state in + state.callCount += 1 + return state.handler + } + if let replaceCourseUnitHandler = replaceCourseUnitHandler { + replaceCourseUnitHandler(courseName, blockId, courseID, verticalIndex, chapters, chapterIndex, sequentialIndex, animated, showVideoNavigation, courseVideoStructure) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let showCourseVerticalViewState = MockoloMutex(MockoloHandlerState ()>()) + public var showCourseVerticalViewCallCount: Int { + return showCourseVerticalViewState.withLock(\.callCount) + } + public var showCourseVerticalViewHandler: (@Sendable (String, String, String, [CourseChapter], Int, Int) -> ())? { + get { showCourseVerticalViewState.withLock(\.handler) } + set { showCourseVerticalViewState.withLock { $0.handler = newValue } } + } + public func showCourseVerticalView(courseID: String, courseName: String, title: String, chapters: [CourseChapter], chapterIndex: Int, sequentialIndex: Int) { + let showCourseVerticalViewHandler = showCourseVerticalViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showCourseVerticalViewHandler = showCourseVerticalViewHandler { + showCourseVerticalViewHandler(courseID, courseName, title, chapters, chapterIndex, sequentialIndex) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let showHandoutsUpdatesViewState = MockoloMutex(MockoloHandlerState ()>()) + public var showHandoutsUpdatesViewCallCount: Int { + return showHandoutsUpdatesViewState.withLock(\.callCount) + } + public var showHandoutsUpdatesViewHandler: (@Sendable (String?, [CourseUpdate]?, Course.CourseRouter, CSSInjector, HandoutsItemType) -> ())? { + get { showHandoutsUpdatesViewState.withLock(\.handler) } + set { showHandoutsUpdatesViewState.withLock { $0.handler = newValue } } + } + public func showHandoutsUpdatesView(handouts: String?, announcements: [CourseUpdate]?, router: Course.CourseRouter, cssInjector: CSSInjector, type: HandoutsItemType) { + let showHandoutsUpdatesViewHandler = showHandoutsUpdatesViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showHandoutsUpdatesViewHandler = showHandoutsUpdatesViewHandler { + showHandoutsUpdatesViewHandler(handouts, announcements, router, cssInjector, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let showCourseComponentState = MockoloMutex(MockoloHandlerState ()>()) + public var showCourseComponentCallCount: Int { + return showCourseComponentState.withLock(\.callCount) + } + public var showCourseComponentHandler: (@Sendable (String, CourseStructure, String) -> ())? { + get { showCourseComponentState.withLock(\.handler) } + set { showCourseComponentState.withLock { $0.handler = newValue } } + } + public func showCourseComponent(componentID: String, courseStructure: CourseStructure, blockLink: String) { + let showCourseComponentHandler = showCourseComponentState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showCourseComponentHandler = showCourseComponentHandler { + showCourseComponentHandler(componentID, courseStructure, blockLink) + } + + } + + private let showDatesAndCalendarState = MockoloMutex(MockoloHandlerState ()>()) + public var showDatesAndCalendarCallCount: Int { + return showDatesAndCalendarState.withLock(\.callCount) + } + public var showDatesAndCalendarHandler: (@Sendable () -> ())? { + get { showDatesAndCalendarState.withLock(\.handler) } + set { showDatesAndCalendarState.withLock { $0.handler = newValue } } + } + public func showDatesAndCalendar() { + let showDatesAndCalendarHandler = showDatesAndCalendarState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDatesAndCalendarHandler = showDatesAndCalendarHandler { + showDatesAndCalendarHandler() + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let showGatedContentErrorState = MockoloMutex(MockoloHandlerState ()>()) + public var showGatedContentErrorCallCount: Int { + return showGatedContentErrorState.withLock(\.callCount) + } + public var showGatedContentErrorHandler: (@Sendable (String) -> ())? { + get { showGatedContentErrorState.withLock(\.handler) } + set { showGatedContentErrorState.withLock { $0.handler = newValue } } + } + public func showGatedContentError(url: String) { + let showGatedContentErrorHandler = showGatedContentErrorState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showGatedContentErrorHandler = showGatedContentErrorHandler { + showGatedContentErrorHandler(url) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class CourseStorageMock: CourseStorage, @unchecked Sendable { + public init() { } + public init(allowedDownloadLargeFile: Bool? = nil, userSettings: UserSettings? = nil) { + self.allowedDownloadLargeFile = allowedDownloadLargeFile + self.userSettings = userSettings + } + + + public private(set) var allowedDownloadLargeFileSetCallCount = 0 + public var allowedDownloadLargeFile: Bool? = nil { didSet { allowedDownloadLargeFileSetCallCount += 1 } } + + public private(set) var userSettingsSetCallCount = 0 + public var userSettings: UserSettings? = nil { didSet { userSettingsSetCallCount += 1 } } +} + +public final class CorePersistenceProtocolMock: CorePersistenceProtocol, @unchecked Sendable { + public init() { } + + + private let setState = MockoloMutex(MockoloHandlerState ()>()) + public var setCallCount: Int { + return setState.withLock(\.callCount) + } + public var setHandler: (@Sendable (Int) -> ())? { + get { setState.withLock(\.handler) } + set { setState.withLock { $0.handler = newValue } } + } + public func set(userId: Int) { + let setHandler = setState.withLock { state in + state.callCount += 1 + return state.handler + } + if let setHandler = setHandler { + setHandler(userId) + } + + } + + private let getUserIDState = MockoloMutex(MockoloHandlerState Int?>()) + public var getUserIDCallCount: Int { + return getUserIDState.withLock(\.callCount) + } + public var getUserIDHandler: (@Sendable () -> Int?)? { + get { getUserIDState.withLock(\.handler) } + set { getUserIDState.withLock { $0.handler = newValue } } + } + public func getUserID() -> Int? { + let getUserIDHandler = getUserIDState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getUserIDHandler = getUserIDHandler { + return getUserIDHandler() + } + return nil + } + + private let publisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var publisherCallCount: Int { + return publisherState.withLock(\.callCount) + } + public var publisherHandler: (@Sendable () throws -> AnyPublisher)? { + get { publisherState.withLock(\.handler) } + set { publisherState.withLock { $0.handler = newValue } } + } + public func publisher() throws -> AnyPublisher { + let publisherHandler = publisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let publisherHandler = publisherHandler { + return try publisherHandler() + } + fatalError("publisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([DownloadDataTask]) -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(tasks: [DownloadDataTask]) { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + addToDownloadQueueHandler(tasks) + } + + } + + private let saveOfflineProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var saveOfflineProgressCallCount: Int { + return saveOfflineProgressState.withLock(\.callCount) + } + public var saveOfflineProgressHandler: (@Sendable (OfflineProgress) async -> ())? { + get { saveOfflineProgressState.withLock(\.handler) } + set { saveOfflineProgressState.withLock { $0.handler = newValue } } + } + public func saveOfflineProgress(progress: OfflineProgress) async { + let saveOfflineProgressHandler = saveOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveOfflineProgressHandler = saveOfflineProgressHandler { + await saveOfflineProgressHandler(progress) + } + + } + + private let loadProgressState = MockoloMutex(MockoloHandlerState OfflineProgress?>()) + public var loadProgressCallCount: Int { + return loadProgressState.withLock(\.callCount) + } + public var loadProgressHandler: (@Sendable (String) async -> OfflineProgress?)? { + get { loadProgressState.withLock(\.handler) } + set { loadProgressState.withLock { $0.handler = newValue } } + } + public func loadProgress(for blockID: String) async -> OfflineProgress? { + let loadProgressHandler = loadProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadProgressHandler = loadProgressHandler { + return await loadProgressHandler(blockID) + } + return nil + } + + private let loadAllOfflineProgressState = MockoloMutex(MockoloHandlerState [OfflineProgress]>()) + public var loadAllOfflineProgressCallCount: Int { + return loadAllOfflineProgressState.withLock(\.callCount) + } + public var loadAllOfflineProgressHandler: (@Sendable () async -> [OfflineProgress])? { + get { loadAllOfflineProgressState.withLock(\.handler) } + set { loadAllOfflineProgressState.withLock { $0.handler = newValue } } + } + public func loadAllOfflineProgress() async -> [OfflineProgress] { + let loadAllOfflineProgressHandler = loadAllOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadAllOfflineProgressHandler = loadAllOfflineProgressHandler { + return await loadAllOfflineProgressHandler() + } + return [OfflineProgress]() + } + + private let deleteProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteProgressCallCount: Int { + return deleteProgressState.withLock(\.callCount) + } + public var deleteProgressHandler: (@Sendable (String) async -> ())? { + get { deleteProgressState.withLock(\.handler) } + set { deleteProgressState.withLock { $0.handler = newValue } } + } + public func deleteProgress(for blockID: String) async { + let deleteProgressHandler = deleteProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteProgressHandler = deleteProgressHandler { + await deleteProgressHandler(blockID) + } + + } + + private let deleteAllProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllProgressCallCount: Int { + return deleteAllProgressState.withLock(\.callCount) + } + public var deleteAllProgressHandler: (@Sendable () async -> ())? { + get { deleteAllProgressState.withLock(\.handler) } + set { deleteAllProgressState.withLock { $0.handler = newValue } } + } + public func deleteAllProgress() async { + let deleteAllProgressHandler = deleteAllProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllProgressHandler = deleteAllProgressHandler { + await deleteAllProgressHandler() + } + + } + + private let addToDownloadQueueBlocksState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueBlocksCallCount: Int { + return addToDownloadQueueBlocksState.withLock(\.callCount) + } + public var addToDownloadQueueBlocksHandler: (@Sendable ([CourseBlock], DownloadQuality) -> ())? { + get { addToDownloadQueueBlocksState.withLock(\.handler) } + set { addToDownloadQueueBlocksState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { + let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksHandler { + addToDownloadQueueBlocksHandler(blocks, downloadQuality) + } + + } + + private let updateTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var updateTaskCallCount: Int { + return updateTaskState.withLock(\.callCount) + } + public var updateTaskHandler: (@Sendable (DownloadDataTask) -> ())? { + get { updateTaskState.withLock(\.handler) } + set { updateTaskState.withLock { $0.handler = newValue } } + } + public func updateTask(task: DownloadDataTask) { + let updateTaskHandler = updateTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateTaskHandler = updateTaskHandler { + updateTaskHandler(task) + } + + } + + private let downloadDataTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadDataTaskCallCount: Int { + return downloadDataTaskState.withLock(\.callCount) + } + public var downloadDataTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadDataTaskState.withLock(\.handler) } + set { downloadDataTaskState.withLock { $0.handler = newValue } } + } + public func downloadDataTask(for blockId: String) async -> DownloadDataTask? { + let downloadDataTaskHandler = downloadDataTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadDataTaskHandler = downloadDataTaskHandler { + return await downloadDataTaskHandler(blockId) + } + return nil + } + + private let getDownloadDataTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksCallCount: Int { + return getDownloadDataTasksState.withLock(\.callCount) + } + public var getDownloadDataTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadDataTasksState.withLock(\.handler) } + set { getDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasks() async -> [DownloadDataTask] { + let getDownloadDataTasksHandler = getDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksHandler = getDownloadDataTasksHandler { + return await getDownloadDataTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadDataTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksForCourseCallCount: Int { + return getDownloadDataTasksForCourseState.withLock(\.callCount) + } + public var getDownloadDataTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadDataTasksForCourseState.withLock(\.handler) } + set { getDownloadDataTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseHandler { + return await getDownloadDataTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let deleteDownloadDataTasksState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteDownloadDataTasksCallCount: Int { + return deleteDownloadDataTasksState.withLock(\.callCount) + } + public var deleteDownloadDataTasksHandler: (@Sendable ([String]) -> ())? { + get { deleteDownloadDataTasksState.withLock(\.handler) } + set { deleteDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func deleteDownloadDataTasks(ids: [String]) { + let deleteDownloadDataTasksHandler = deleteDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteDownloadDataTasksHandler = deleteDownloadDataTasksHandler { + deleteDownloadDataTasksHandler(ids) + } + + } +} + +public final class CoursePersistenceProtocolMock: CoursePersistenceProtocol, @unchecked Sendable { + public init() { } + + + private let loadEnrollmentsState = MockoloMutex(MockoloHandlerState [Core.CourseItem]>()) + public var loadEnrollmentsCallCount: Int { + return loadEnrollmentsState.withLock(\.callCount) + } + public var loadEnrollmentsHandler: (@Sendable () async throws -> [Core.CourseItem])? { + get { loadEnrollmentsState.withLock(\.handler) } + set { loadEnrollmentsState.withLock { $0.handler = newValue } } + } + public func loadEnrollments() async throws -> [Core.CourseItem] { + let loadEnrollmentsHandler = loadEnrollmentsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadEnrollmentsHandler = loadEnrollmentsHandler { + return try await loadEnrollmentsHandler() + } + return [Core.CourseItem]() + } + + private let saveEnrollmentsState = MockoloMutex(MockoloHandlerState ()>()) + public var saveEnrollmentsCallCount: Int { + return saveEnrollmentsState.withLock(\.callCount) + } + public var saveEnrollmentsHandler: (@Sendable ([Core.CourseItem]) async -> ())? { + get { saveEnrollmentsState.withLock(\.handler) } + set { saveEnrollmentsState.withLock { $0.handler = newValue } } + } + public func saveEnrollments(items: [Core.CourseItem]) async { + let saveEnrollmentsHandler = saveEnrollmentsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveEnrollmentsHandler = saveEnrollmentsHandler { + await saveEnrollmentsHandler(items) + } + + } + + private let loadCourseStructureState = MockoloMutex(MockoloHandlerState DataLayer.CourseStructure>()) + public var loadCourseStructureCallCount: Int { + return loadCourseStructureState.withLock(\.callCount) + } + public var loadCourseStructureHandler: (@Sendable (String) async throws -> DataLayer.CourseStructure)? { + get { loadCourseStructureState.withLock(\.handler) } + set { loadCourseStructureState.withLock { $0.handler = newValue } } + } + public func loadCourseStructure(courseID: String) async throws -> DataLayer.CourseStructure { + let loadCourseStructureHandler = loadCourseStructureState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadCourseStructureHandler = loadCourseStructureHandler { + return try await loadCourseStructureHandler(courseID) + } + fatalError("loadCourseStructureHandler returns can't have a default value thus its handler must be set") + } + + private let saveCourseStructureState = MockoloMutex(MockoloHandlerState ()>()) + public var saveCourseStructureCallCount: Int { + return saveCourseStructureState.withLock(\.callCount) + } + public var saveCourseStructureHandler: (@Sendable (DataLayer.CourseStructure) async -> ())? { + get { saveCourseStructureState.withLock(\.handler) } + set { saveCourseStructureState.withLock { $0.handler = newValue } } + } + public func saveCourseStructure(structure: DataLayer.CourseStructure) async { + let saveCourseStructureHandler = saveCourseStructureState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveCourseStructureHandler = saveCourseStructureHandler { + await saveCourseStructureHandler(structure) + } + + } + + private let saveSubtitlesState = MockoloMutex(MockoloHandlerState ()>()) + public var saveSubtitlesCallCount: Int { + return saveSubtitlesState.withLock(\.callCount) + } + public var saveSubtitlesHandler: (@Sendable (String, String) async -> ())? { + get { saveSubtitlesState.withLock(\.handler) } + set { saveSubtitlesState.withLock { $0.handler = newValue } } + } + public func saveSubtitles(url: String, subtitlesString: String) async { + let saveSubtitlesHandler = saveSubtitlesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveSubtitlesHandler = saveSubtitlesHandler { + await saveSubtitlesHandler(url, subtitlesString) + } + + } + + private let loadSubtitlesState = MockoloMutex(MockoloHandlerState String?>()) + public var loadSubtitlesCallCount: Int { + return loadSubtitlesState.withLock(\.callCount) + } + public var loadSubtitlesHandler: (@Sendable (String) async -> String?)? { + get { loadSubtitlesState.withLock(\.handler) } + set { loadSubtitlesState.withLock { $0.handler = newValue } } + } + public func loadSubtitles(url: String) async -> String? { + let loadSubtitlesHandler = loadSubtitlesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadSubtitlesHandler = loadSubtitlesHandler { + return await loadSubtitlesHandler(url) + } + return nil + } + + private let saveCourseDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var saveCourseDatesCallCount: Int { + return saveCourseDatesState.withLock(\.callCount) + } + public var saveCourseDatesHandler: (@Sendable (String, CourseDates) async -> ())? { + get { saveCourseDatesState.withLock(\.handler) } + set { saveCourseDatesState.withLock { $0.handler = newValue } } + } + public func saveCourseDates(courseID: String, courseDates: CourseDates) async { + let saveCourseDatesHandler = saveCourseDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveCourseDatesHandler = saveCourseDatesHandler { + await saveCourseDatesHandler(courseID, courseDates) + } + + } + + private let loadCourseDatesState = MockoloMutex(MockoloHandlerState CourseDates>()) + public var loadCourseDatesCallCount: Int { + return loadCourseDatesState.withLock(\.callCount) + } + public var loadCourseDatesHandler: (@Sendable (String) async throws -> CourseDates)? { + get { loadCourseDatesState.withLock(\.handler) } + set { loadCourseDatesState.withLock { $0.handler = newValue } } + } + public func loadCourseDates(courseID: String) async throws -> CourseDates { + let loadCourseDatesHandler = loadCourseDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadCourseDatesHandler = loadCourseDatesHandler { + return try await loadCourseDatesHandler(courseID) + } + fatalError("loadCourseDatesHandler returns can't have a default value thus its handler must be set") + } + + private let saveCourseProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var saveCourseProgressCallCount: Int { + return saveCourseProgressState.withLock(\.callCount) + } + public var saveCourseProgressHandler: (@Sendable (String, CourseProgressDetails) async -> ())? { + get { saveCourseProgressState.withLock(\.handler) } + set { saveCourseProgressState.withLock { $0.handler = newValue } } + } + public func saveCourseProgress(courseID: String, courseProgress: CourseProgressDetails) async { + let saveCourseProgressHandler = saveCourseProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveCourseProgressHandler = saveCourseProgressHandler { + await saveCourseProgressHandler(courseID, courseProgress) + } + + } + + private let loadCourseProgressState = MockoloMutex(MockoloHandlerState CourseProgressDetails>()) + public var loadCourseProgressCallCount: Int { + return loadCourseProgressState.withLock(\.callCount) + } + public var loadCourseProgressHandler: (@Sendable (String) async throws -> CourseProgressDetails)? { + get { loadCourseProgressState.withLock(\.handler) } + set { loadCourseProgressState.withLock { $0.handler = newValue } } + } + public func loadCourseProgress(courseID: String) async throws -> CourseProgressDetails { + let loadCourseProgressHandler = loadCourseProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadCourseProgressHandler = loadCourseProgressHandler { + return try await loadCourseProgressHandler(courseID) + } + fatalError("loadCourseProgressHandler returns can't have a default value thus its handler must be set") + } + + private let updateLocalVideoProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var updateLocalVideoProgressCallCount: Int { + return updateLocalVideoProgressState.withLock(\.callCount) + } + public var updateLocalVideoProgressHandler: (@Sendable (String, Double) async -> ())? { + get { updateLocalVideoProgressState.withLock(\.handler) } + set { updateLocalVideoProgressState.withLock { $0.handler = newValue } } + } + public func updateLocalVideoProgress(blockID: String, progress: Double) async { + let updateLocalVideoProgressHandler = updateLocalVideoProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateLocalVideoProgressHandler = updateLocalVideoProgressHandler { + await updateLocalVideoProgressHandler(blockID, progress) + } + + } + + private let loadLocalVideoProgressState = MockoloMutex(MockoloHandlerState Double?>()) + public var loadLocalVideoProgressCallCount: Int { + return loadLocalVideoProgressState.withLock(\.callCount) + } + public var loadLocalVideoProgressHandler: (@Sendable (String) async -> Double?)? { + get { loadLocalVideoProgressState.withLock(\.handler) } + set { loadLocalVideoProgressState.withLock { $0.handler = newValue } } + } + public func loadLocalVideoProgress(blockID: String) async -> Double? { + let loadLocalVideoProgressHandler = loadLocalVideoProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadLocalVideoProgressHandler = loadLocalVideoProgressHandler { + return await loadLocalVideoProgressHandler(blockID) + } + return nil + } +} + +public final class CourseInteractorProtocolMock: CourseInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseBlocksCallCount: Int { + return getCourseBlocksState.withLock(\.callCount) + } + public var getCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getCourseBlocksState.withLock(\.handler) } + set { getCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseBlocks(courseID: String) async throws -> CourseStructure { + let getCourseBlocksHandler = getCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseBlocksHandler = getCourseBlocksHandler { + return try await getCourseBlocksHandler(courseID) + } + fatalError("getCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getCourseVideoBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseVideoBlocksCallCount: Int { + return getCourseVideoBlocksState.withLock(\.callCount) + } + public var getCourseVideoBlocksHandler: (@Sendable (CourseStructure) async -> CourseStructure)? { + get { getCourseVideoBlocksState.withLock(\.handler) } + set { getCourseVideoBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseVideoBlocks(fullStructure: CourseStructure) async -> CourseStructure { + let getCourseVideoBlocksHandler = getCourseVideoBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseVideoBlocksHandler = getCourseVideoBlocksHandler { + return await getCourseVideoBlocksHandler(fullStructure) + } + fatalError("getCourseVideoBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getCourseAssignmentBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseAssignmentBlocksCallCount: Int { + return getCourseAssignmentBlocksState.withLock(\.callCount) + } + public var getCourseAssignmentBlocksHandler: (@Sendable (CourseStructure) async -> CourseStructure)? { + get { getCourseAssignmentBlocksState.withLock(\.handler) } + set { getCourseAssignmentBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseAssignmentBlocks(fullStructure: CourseStructure) async -> CourseStructure { + let getCourseAssignmentBlocksHandler = getCourseAssignmentBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseAssignmentBlocksHandler = getCourseAssignmentBlocksHandler { + return await getCourseAssignmentBlocksHandler(fullStructure) + } + fatalError("getCourseAssignmentBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getLoadedCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getLoadedCourseBlocksCallCount: Int { + return getLoadedCourseBlocksState.withLock(\.callCount) + } + public var getLoadedCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getLoadedCourseBlocksState.withLock(\.handler) } + set { getLoadedCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure { + let getLoadedCourseBlocksHandler = getLoadedCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseBlocksHandler = getLoadedCourseBlocksHandler { + return try await getLoadedCourseBlocksHandler(courseID) + } + fatalError("getLoadedCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getSequentialsContainsBlocksState = MockoloMutex(MockoloHandlerState [CourseSequential]>()) + public var getSequentialsContainsBlocksCallCount: Int { + return getSequentialsContainsBlocksState.withLock(\.callCount) + } + public var getSequentialsContainsBlocksHandler: (@Sendable ([String], String) async throws -> [CourseSequential])? { + get { getSequentialsContainsBlocksState.withLock(\.handler) } + set { getSequentialsContainsBlocksState.withLock { $0.handler = newValue } } + } + public func getSequentialsContainsBlocks(blockIds: [String], courseID: String) async throws -> [CourseSequential] { + let getSequentialsContainsBlocksHandler = getSequentialsContainsBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getSequentialsContainsBlocksHandler = getSequentialsContainsBlocksHandler { + return try await getSequentialsContainsBlocksHandler(blockIds, courseID) + } + return [CourseSequential]() + } + + private let blockCompletionRequestState = MockoloMutex(MockoloHandlerState ()>()) + public var blockCompletionRequestCallCount: Int { + return blockCompletionRequestState.withLock(\.callCount) + } + public var blockCompletionRequestHandler: (@Sendable (String, String) async throws -> ())? { + get { blockCompletionRequestState.withLock(\.handler) } + set { blockCompletionRequestState.withLock { $0.handler = newValue } } + } + public func blockCompletionRequest(courseID: String, blockID: String) async throws { + let blockCompletionRequestHandler = blockCompletionRequestState.withLock { state in + state.callCount += 1 + return state.handler + } + if let blockCompletionRequestHandler = blockCompletionRequestHandler { + try await blockCompletionRequestHandler(courseID, blockID) + } + + } + + private let getHandoutsState = MockoloMutex(MockoloHandlerState String?>()) + public var getHandoutsCallCount: Int { + return getHandoutsState.withLock(\.callCount) + } + public var getHandoutsHandler: (@Sendable (String) async throws -> String?)? { + get { getHandoutsState.withLock(\.handler) } + set { getHandoutsState.withLock { $0.handler = newValue } } + } + public func getHandouts(courseID: String) async throws -> String? { + let getHandoutsHandler = getHandoutsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getHandoutsHandler = getHandoutsHandler { + return try await getHandoutsHandler(courseID) + } + return nil + } + + private let getUpdatesState = MockoloMutex(MockoloHandlerState [CourseUpdate]>()) + public var getUpdatesCallCount: Int { + return getUpdatesState.withLock(\.callCount) + } + public var getUpdatesHandler: (@Sendable (String) async throws -> [CourseUpdate])? { + get { getUpdatesState.withLock(\.handler) } + set { getUpdatesState.withLock { $0.handler = newValue } } + } + public func getUpdates(courseID: String) async throws -> [CourseUpdate] { + let getUpdatesHandler = getUpdatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getUpdatesHandler = getUpdatesHandler { + return try await getUpdatesHandler(courseID) + } + return [CourseUpdate]() + } + + private let resumeBlockState = MockoloMutex(MockoloHandlerState ResumeBlock>()) + public var resumeBlockCallCount: Int { + return resumeBlockState.withLock(\.callCount) + } + public var resumeBlockHandler: (@Sendable (String) async throws -> ResumeBlock)? { + get { resumeBlockState.withLock(\.handler) } + set { resumeBlockState.withLock { $0.handler = newValue } } + } + public func resumeBlock(courseID: String) async throws -> ResumeBlock { + let resumeBlockHandler = resumeBlockState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resumeBlockHandler = resumeBlockHandler { + return try await resumeBlockHandler(courseID) + } + fatalError("resumeBlockHandler returns can't have a default value thus its handler must be set") + } + + private let getSubtitlesState = MockoloMutex(MockoloHandlerState [Subtitle]>()) + public var getSubtitlesCallCount: Int { + return getSubtitlesState.withLock(\.callCount) + } + public var getSubtitlesHandler: (@Sendable (String, String) async throws -> [Subtitle])? { + get { getSubtitlesState.withLock(\.handler) } + set { getSubtitlesState.withLock { $0.handler = newValue } } + } + public func getSubtitles(url: String, selectedLanguage: String) async throws -> [Subtitle] { + let getSubtitlesHandler = getSubtitlesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getSubtitlesHandler = getSubtitlesHandler { + return try await getSubtitlesHandler(url, selectedLanguage) + } + return [Subtitle]() + } + + private let getCourseDatesState = MockoloMutex(MockoloHandlerState CourseDates>()) + public var getCourseDatesCallCount: Int { + return getCourseDatesState.withLock(\.callCount) + } + public var getCourseDatesHandler: (@Sendable (String) async throws -> CourseDates)? { + get { getCourseDatesState.withLock(\.handler) } + set { getCourseDatesState.withLock { $0.handler = newValue } } + } + public func getCourseDates(courseID: String) async throws -> CourseDates { + let getCourseDatesHandler = getCourseDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDatesHandler = getCourseDatesHandler { + return try await getCourseDatesHandler(courseID) + } + fatalError("getCourseDatesHandler returns can't have a default value thus its handler must be set") + } + + private let getCourseDeadlineInfoState = MockoloMutex(MockoloHandlerState CourseDateBanner>()) + public var getCourseDeadlineInfoCallCount: Int { + return getCourseDeadlineInfoState.withLock(\.callCount) + } + public var getCourseDeadlineInfoHandler: (@Sendable (String) async throws -> CourseDateBanner)? { + get { getCourseDeadlineInfoState.withLock(\.handler) } + set { getCourseDeadlineInfoState.withLock { $0.handler = newValue } } + } + public func getCourseDeadlineInfo(courseID: String) async throws -> CourseDateBanner { + let getCourseDeadlineInfoHandler = getCourseDeadlineInfoState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDeadlineInfoHandler = getCourseDeadlineInfoHandler { + return try await getCourseDeadlineInfoHandler(courseID) + } + fatalError("getCourseDeadlineInfoHandler returns can't have a default value thus its handler must be set") + } + + private let shiftDueDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var shiftDueDatesCallCount: Int { + return shiftDueDatesState.withLock(\.callCount) + } + public var shiftDueDatesHandler: (@Sendable (String) async throws -> ())? { + get { shiftDueDatesState.withLock(\.handler) } + set { shiftDueDatesState.withLock { $0.handler = newValue } } + } + public func shiftDueDates(courseID: String) async throws { + let shiftDueDatesHandler = shiftDueDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let shiftDueDatesHandler = shiftDueDatesHandler { + try await shiftDueDatesHandler(courseID) + } + + } + + private let updateLocalVideoProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var updateLocalVideoProgressCallCount: Int { + return updateLocalVideoProgressState.withLock(\.callCount) + } + public var updateLocalVideoProgressHandler: (@Sendable (String, Double) async -> ())? { + get { updateLocalVideoProgressState.withLock(\.handler) } + set { updateLocalVideoProgressState.withLock { $0.handler = newValue } } + } + public func updateLocalVideoProgress(blockID: String, progress: Double) async { + let updateLocalVideoProgressHandler = updateLocalVideoProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateLocalVideoProgressHandler = updateLocalVideoProgressHandler { + await updateLocalVideoProgressHandler(blockID, progress) + } + + } + + private let loadLocalVideoProgressState = MockoloMutex(MockoloHandlerState Double?>()) + public var loadLocalVideoProgressCallCount: Int { + return loadLocalVideoProgressState.withLock(\.callCount) + } + public var loadLocalVideoProgressHandler: (@Sendable (String) async -> Double?)? { + get { loadLocalVideoProgressState.withLock(\.handler) } + set { loadLocalVideoProgressState.withLock { $0.handler = newValue } } + } + public func loadLocalVideoProgress(blockID: String) async -> Double? { + let loadLocalVideoProgressHandler = loadLocalVideoProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadLocalVideoProgressHandler = loadLocalVideoProgressHandler { + return await loadLocalVideoProgressHandler(blockID) + } + return nil + } + + private let enrichCourseStructureWithLocalProgressState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var enrichCourseStructureWithLocalProgressCallCount: Int { + return enrichCourseStructureWithLocalProgressState.withLock(\.callCount) + } + public var enrichCourseStructureWithLocalProgressHandler: (@Sendable (CourseStructure) async -> CourseStructure)? { + get { enrichCourseStructureWithLocalProgressState.withLock(\.handler) } + set { enrichCourseStructureWithLocalProgressState.withLock { $0.handler = newValue } } + } + public func enrichCourseStructureWithLocalProgress(_ structure: CourseStructure) async -> CourseStructure { + let enrichCourseStructureWithLocalProgressHandler = enrichCourseStructureWithLocalProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let enrichCourseStructureWithLocalProgressHandler = enrichCourseStructureWithLocalProgressHandler { + return await enrichCourseStructureWithLocalProgressHandler(structure) + } + fatalError("enrichCourseStructureWithLocalProgressHandler returns can't have a default value thus its handler must be set") + } + + private let getCourseProgressState = MockoloMutex(MockoloHandlerState CourseProgressDetails>()) + public var getCourseProgressCallCount: Int { + return getCourseProgressState.withLock(\.callCount) + } + public var getCourseProgressHandler: (@Sendable (String) async throws -> CourseProgressDetails)? { + get { getCourseProgressState.withLock(\.handler) } + set { getCourseProgressState.withLock { $0.handler = newValue } } + } + public func getCourseProgress(courseID: String) async throws -> CourseProgressDetails { + let getCourseProgressHandler = getCourseProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseProgressHandler = getCourseProgressHandler { + return try await getCourseProgressHandler(courseID) + } + fatalError("getCourseProgressHandler returns can't have a default value thus its handler must be set") + } + + private let getCourseProgressOfflineState = MockoloMutex(MockoloHandlerState CourseProgressDetails>()) + public var getCourseProgressOfflineCallCount: Int { + return getCourseProgressOfflineState.withLock(\.callCount) + } + public var getCourseProgressOfflineHandler: (@Sendable (String) async throws -> CourseProgressDetails)? { + get { getCourseProgressOfflineState.withLock(\.handler) } + set { getCourseProgressOfflineState.withLock { $0.handler = newValue } } + } + public func getCourseProgressOffline(courseID: String) async throws -> CourseProgressDetails { + let getCourseProgressOfflineHandler = getCourseProgressOfflineState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseProgressOfflineHandler = getCourseProgressOfflineHandler { + return try await getCourseProgressOfflineHandler(courseID) + } + fatalError("getCourseProgressOfflineHandler returns can't have a default value thus its handler must be set") + } + + private let getAllVideosForNavigationState = MockoloMutex(MockoloHandlerState [CourseBlock]>()) + public var getAllVideosForNavigationCallCount: Int { + return getAllVideosForNavigationState.withLock(\.callCount) + } + public var getAllVideosForNavigationHandler: (@Sendable (CourseStructure) async throws -> [CourseBlock])? { + get { getAllVideosForNavigationState.withLock(\.handler) } + set { getAllVideosForNavigationState.withLock { $0.handler = newValue } } + } + public func getAllVideosForNavigation(structure course: CourseStructure) async throws -> [CourseBlock] { + let getAllVideosForNavigationHandler = getAllVideosForNavigationState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getAllVideosForNavigationHandler = getAllVideosForNavigationHandler { + return try await getAllVideosForNavigationHandler(course) + } + return [CourseBlock]() + } +} + +public final class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseBlocksCallCount: Int { + return getCourseBlocksState.withLock(\.callCount) + } + public var getCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getCourseBlocksState.withLock(\.handler) } + set { getCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseBlocks(courseID: String) async throws -> CourseStructure { + let getCourseBlocksHandler = getCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseBlocksHandler = getCourseBlocksHandler { + return try await getCourseBlocksHandler(courseID) + } + fatalError("getCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getLoadedCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getLoadedCourseBlocksCallCount: Int { + return getLoadedCourseBlocksState.withLock(\.callCount) + } + public var getLoadedCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getLoadedCourseBlocksState.withLock(\.handler) } + set { getLoadedCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure { + let getLoadedCourseBlocksHandler = getLoadedCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseBlocksHandler = getLoadedCourseBlocksHandler { + return try await getLoadedCourseBlocksHandler(courseID) + } + fatalError("getLoadedCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let shiftDueDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var shiftDueDatesCallCount: Int { + return shiftDueDatesState.withLock(\.callCount) + } + public var shiftDueDatesHandler: (@Sendable (String) async throws -> ())? { + get { shiftDueDatesState.withLock(\.handler) } + set { shiftDueDatesState.withLock { $0.handler = newValue } } + } + public func shiftDueDates(courseID: String) async throws { + let shiftDueDatesHandler = shiftDueDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let shiftDueDatesHandler = shiftDueDatesHandler { + try await shiftDueDatesHandler(courseID) + } + + } +} + +public final class CourseDownloadHelperProtocolMock: CourseDownloadHelperProtocol, @unchecked Sendable { + public init() { } + public init(value: CourseDownloadValue? = nil, courseStructure: CourseStructure? = nil, videoQuality: DownloadQuality) { + self.value = value + self.courseStructure = courseStructure + self._videoQuality = videoQuality + } + + + + public var value: CourseDownloadValue? = nil + + public private(set) var courseStructureSetCallCount = 0 + public var courseStructure: CourseStructure? = nil { didSet { courseStructureSetCallCount += 1 } } + + public private(set) var videoQualitySetCallCount = 0 + private var _videoQuality: DownloadQuality! { didSet { videoQualitySetCallCount += 1 } } + public var videoQuality: DownloadQuality { + get { return _videoQuality } + set { _videoQuality = newValue } + } + + private let publisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var publisherCallCount: Int { + return publisherState.withLock(\.callCount) + } + public var publisherHandler: (@Sendable () -> AnyPublisher)? { + get { publisherState.withLock(\.handler) } + set { publisherState.withLock { $0.handler = newValue } } + } + public func publisher() -> AnyPublisher { + let publisherHandler = publisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let publisherHandler = publisherHandler { + return publisherHandler() + } + fatalError("publisherHandler returns can't have a default value thus its handler must be set") + } + + private let progressPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var progressPublisherCallCount: Int { + return progressPublisherState.withLock(\.callCount) + } + public var progressPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { progressPublisherState.withLock(\.handler) } + set { progressPublisherState.withLock { $0.handler = newValue } } + } + public func progressPublisher() -> AnyPublisher { + let progressPublisherHandler = progressPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let progressPublisherHandler = progressPublisherHandler { + return progressPublisherHandler() + } + fatalError("progressPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let refreshValueState = MockoloMutex(MockoloHandlerState ()>()) + public var refreshValueCallCount: Int { + return refreshValueState.withLock(\.callCount) + } + public var refreshValueHandler: (@Sendable () -> ())? { + get { refreshValueState.withLock(\.handler) } + set { refreshValueState.withLock { $0.handler = newValue } } + } + public func refreshValue() { + let refreshValueHandler = refreshValueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let refreshValueHandler = refreshValueHandler { + refreshValueHandler() + } + + } + + private let sizeForState = MockoloMutex(MockoloHandlerState Int?>()) + public var sizeForCallCount: Int { + return sizeForState.withLock(\.callCount) + } + public var sizeForHandler: (@Sendable (CourseBlock) -> Int?)? { + get { sizeForState.withLock(\.handler) } + set { sizeForState.withLock { $0.handler = newValue } } + } + public func sizeFor(block: CourseBlock) -> Int? { + let sizeForHandler = sizeForState.withLock { state in + state.callCount += 1 + return state.handler + } + if let sizeForHandler = sizeForHandler { + return sizeForHandler(block) + } + return nil + } + + private let sizeForBlocksState = MockoloMutex(MockoloHandlerState Int>()) + public var sizeForBlocksCallCount: Int { + return sizeForBlocksState.withLock(\.callCount) + } + public var sizeForBlocksHandler: (@Sendable ([CourseBlock]) -> Int)? { + get { sizeForBlocksState.withLock(\.handler) } + set { sizeForBlocksState.withLock { $0.handler = newValue } } + } + public func sizeFor(blocks: [CourseBlock]) -> Int { + let sizeForBlocksHandler = sizeForBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let sizeForBlocksHandler = sizeForBlocksHandler { + return sizeForBlocksHandler(blocks) + } + return 0 + } + + private let sizeForSequentialState = MockoloMutex(MockoloHandlerState Int>()) + public var sizeForSequentialCallCount: Int { + return sizeForSequentialState.withLock(\.callCount) + } + public var sizeForSequentialHandler: (@Sendable (CourseSequential) -> Int)? { + get { sizeForSequentialState.withLock(\.handler) } + set { sizeForSequentialState.withLock { $0.handler = newValue } } + } + public func sizeFor(sequential: CourseSequential) -> Int { + let sizeForSequentialHandler = sizeForSequentialState.withLock { state in + state.callCount += 1 + return state.handler + } + if let sizeForSequentialHandler = sizeForSequentialHandler { + return sizeForSequentialHandler(sequential) + } + return 0 + } + + private let sizeForSequentialsState = MockoloMutex(MockoloHandlerState Int>()) + public var sizeForSequentialsCallCount: Int { + return sizeForSequentialsState.withLock(\.callCount) + } + public var sizeForSequentialsHandler: (@Sendable ([CourseSequential]) -> Int)? { + get { sizeForSequentialsState.withLock(\.handler) } + set { sizeForSequentialsState.withLock { $0.handler = newValue } } + } + public func sizeFor(sequentials: [CourseSequential]) -> Int { + let sizeForSequentialsHandler = sizeForSequentialsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let sizeForSequentialsHandler = sizeForSequentialsHandler { + return sizeForSequentialsHandler(sequentials) + } + return 0 + } + + private let cancelDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCallCount: Int { + return cancelDownloadingState.withLock(\.callCount) + } + public var cancelDownloadingHandler: (@Sendable (DownloadDataTask) async throws -> ())? { + get { cancelDownloadingState.withLock(\.handler) } + set { cancelDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(task: DownloadDataTask) async throws { + let cancelDownloadingHandler = cancelDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingHandler = cancelDownloadingHandler { + try await cancelDownloadingHandler(task) + } + + } +} + +public final class CourseRepositoryProtocolMock: CourseRepositoryProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseBlocksCallCount: Int { + return getCourseBlocksState.withLock(\.callCount) + } + public var getCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getCourseBlocksState.withLock(\.handler) } + set { getCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseBlocks(courseID: String) async throws -> CourseStructure { + let getCourseBlocksHandler = getCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseBlocksHandler = getCourseBlocksHandler { + return try await getCourseBlocksHandler(courseID) + } + fatalError("getCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getLoadedCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getLoadedCourseBlocksCallCount: Int { + return getLoadedCourseBlocksState.withLock(\.callCount) + } + public var getLoadedCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getLoadedCourseBlocksState.withLock(\.handler) } + set { getLoadedCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure { + let getLoadedCourseBlocksHandler = getLoadedCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseBlocksHandler = getLoadedCourseBlocksHandler { + return try await getLoadedCourseBlocksHandler(courseID) + } + fatalError("getLoadedCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let blockCompletionRequestState = MockoloMutex(MockoloHandlerState ()>()) + public var blockCompletionRequestCallCount: Int { + return blockCompletionRequestState.withLock(\.callCount) + } + public var blockCompletionRequestHandler: (@Sendable (String, String) async throws -> ())? { + get { blockCompletionRequestState.withLock(\.handler) } + set { blockCompletionRequestState.withLock { $0.handler = newValue } } + } + public func blockCompletionRequest(courseID: String, blockID: String) async throws { + let blockCompletionRequestHandler = blockCompletionRequestState.withLock { state in + state.callCount += 1 + return state.handler + } + if let blockCompletionRequestHandler = blockCompletionRequestHandler { + try await blockCompletionRequestHandler(courseID, blockID) + } + + } + + private let getHandoutsState = MockoloMutex(MockoloHandlerState String?>()) + public var getHandoutsCallCount: Int { + return getHandoutsState.withLock(\.callCount) + } + public var getHandoutsHandler: (@Sendable (String) async throws -> String?)? { + get { getHandoutsState.withLock(\.handler) } + set { getHandoutsState.withLock { $0.handler = newValue } } + } + public func getHandouts(courseID: String) async throws -> String? { + let getHandoutsHandler = getHandoutsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getHandoutsHandler = getHandoutsHandler { + return try await getHandoutsHandler(courseID) + } + return nil + } + + private let getUpdatesState = MockoloMutex(MockoloHandlerState [CourseUpdate]>()) + public var getUpdatesCallCount: Int { + return getUpdatesState.withLock(\.callCount) + } + public var getUpdatesHandler: (@Sendable (String) async throws -> [CourseUpdate])? { + get { getUpdatesState.withLock(\.handler) } + set { getUpdatesState.withLock { $0.handler = newValue } } + } + public func getUpdates(courseID: String) async throws -> [CourseUpdate] { + let getUpdatesHandler = getUpdatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getUpdatesHandler = getUpdatesHandler { + return try await getUpdatesHandler(courseID) + } + return [CourseUpdate]() + } + + private let resumeBlockState = MockoloMutex(MockoloHandlerState ResumeBlock>()) + public var resumeBlockCallCount: Int { + return resumeBlockState.withLock(\.callCount) + } + public var resumeBlockHandler: (@Sendable (String) async throws -> ResumeBlock)? { + get { resumeBlockState.withLock(\.handler) } + set { resumeBlockState.withLock { $0.handler = newValue } } + } + public func resumeBlock(courseID: String) async throws -> ResumeBlock { + let resumeBlockHandler = resumeBlockState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resumeBlockHandler = resumeBlockHandler { + return try await resumeBlockHandler(courseID) + } + fatalError("resumeBlockHandler returns can't have a default value thus its handler must be set") + } + + private let getSubtitlesState = MockoloMutex(MockoloHandlerState String>()) + public var getSubtitlesCallCount: Int { + return getSubtitlesState.withLock(\.callCount) + } + public var getSubtitlesHandler: (@Sendable (String, String) async throws -> String)? { + get { getSubtitlesState.withLock(\.handler) } + set { getSubtitlesState.withLock { $0.handler = newValue } } + } + public func getSubtitles(url: String, selectedLanguage: String) async throws -> String { + let getSubtitlesHandler = getSubtitlesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getSubtitlesHandler = getSubtitlesHandler { + return try await getSubtitlesHandler(url, selectedLanguage) + } + return "" + } + + private let getCourseDatesState = MockoloMutex(MockoloHandlerState CourseDates>()) + public var getCourseDatesCallCount: Int { + return getCourseDatesState.withLock(\.callCount) + } + public var getCourseDatesHandler: (@Sendable (String) async throws -> CourseDates)? { + get { getCourseDatesState.withLock(\.handler) } + set { getCourseDatesState.withLock { $0.handler = newValue } } + } + public func getCourseDates(courseID: String) async throws -> CourseDates { + let getCourseDatesHandler = getCourseDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDatesHandler = getCourseDatesHandler { + return try await getCourseDatesHandler(courseID) + } + fatalError("getCourseDatesHandler returns can't have a default value thus its handler must be set") + } + + private let getCourseDatesOfflineState = MockoloMutex(MockoloHandlerState CourseDates>()) + public var getCourseDatesOfflineCallCount: Int { + return getCourseDatesOfflineState.withLock(\.callCount) + } + public var getCourseDatesOfflineHandler: (@Sendable (String) async throws -> CourseDates)? { + get { getCourseDatesOfflineState.withLock(\.handler) } + set { getCourseDatesOfflineState.withLock { $0.handler = newValue } } + } + public func getCourseDatesOffline(courseID: String) async throws -> CourseDates { + let getCourseDatesOfflineHandler = getCourseDatesOfflineState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDatesOfflineHandler = getCourseDatesOfflineHandler { + return try await getCourseDatesOfflineHandler(courseID) + } + fatalError("getCourseDatesOfflineHandler returns can't have a default value thus its handler must be set") + } + + private let getCourseDeadlineInfoState = MockoloMutex(MockoloHandlerState CourseDateBanner>()) + public var getCourseDeadlineInfoCallCount: Int { + return getCourseDeadlineInfoState.withLock(\.callCount) + } + public var getCourseDeadlineInfoHandler: (@Sendable (String) async throws -> CourseDateBanner)? { + get { getCourseDeadlineInfoState.withLock(\.handler) } + set { getCourseDeadlineInfoState.withLock { $0.handler = newValue } } + } + public func getCourseDeadlineInfo(courseID: String) async throws -> CourseDateBanner { + let getCourseDeadlineInfoHandler = getCourseDeadlineInfoState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDeadlineInfoHandler = getCourseDeadlineInfoHandler { + return try await getCourseDeadlineInfoHandler(courseID) + } + fatalError("getCourseDeadlineInfoHandler returns can't have a default value thus its handler must be set") + } + + private let shiftDueDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var shiftDueDatesCallCount: Int { + return shiftDueDatesState.withLock(\.callCount) + } + public var shiftDueDatesHandler: (@Sendable (String) async throws -> ())? { + get { shiftDueDatesState.withLock(\.handler) } + set { shiftDueDatesState.withLock { $0.handler = newValue } } + } + public func shiftDueDates(courseID: String) async throws { + let shiftDueDatesHandler = shiftDueDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let shiftDueDatesHandler = shiftDueDatesHandler { + try await shiftDueDatesHandler(courseID) + } + + } + + private let updateLocalVideoProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var updateLocalVideoProgressCallCount: Int { + return updateLocalVideoProgressState.withLock(\.callCount) + } + public var updateLocalVideoProgressHandler: (@Sendable (String, Double) async -> ())? { + get { updateLocalVideoProgressState.withLock(\.handler) } + set { updateLocalVideoProgressState.withLock { $0.handler = newValue } } + } + public func updateLocalVideoProgress(blockID: String, progress: Double) async { + let updateLocalVideoProgressHandler = updateLocalVideoProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateLocalVideoProgressHandler = updateLocalVideoProgressHandler { + await updateLocalVideoProgressHandler(blockID, progress) + } + + } + + private let loadLocalVideoProgressState = MockoloMutex(MockoloHandlerState Double?>()) + public var loadLocalVideoProgressCallCount: Int { + return loadLocalVideoProgressState.withLock(\.callCount) + } + public var loadLocalVideoProgressHandler: (@Sendable (String) async -> Double?)? { + get { loadLocalVideoProgressState.withLock(\.handler) } + set { loadLocalVideoProgressState.withLock { $0.handler = newValue } } + } + public func loadLocalVideoProgress(blockID: String) async -> Double? { + let loadLocalVideoProgressHandler = loadLocalVideoProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadLocalVideoProgressHandler = loadLocalVideoProgressHandler { + return await loadLocalVideoProgressHandler(blockID) + } + return nil + } + + private let getCourseProgressState = MockoloMutex(MockoloHandlerState CourseProgressDetails>()) + public var getCourseProgressCallCount: Int { + return getCourseProgressState.withLock(\.callCount) + } + public var getCourseProgressHandler: (@Sendable (String) async throws -> CourseProgressDetails)? { + get { getCourseProgressState.withLock(\.handler) } + set { getCourseProgressState.withLock { $0.handler = newValue } } + } + public func getCourseProgress(courseID: String) async throws -> CourseProgressDetails { + let getCourseProgressHandler = getCourseProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseProgressHandler = getCourseProgressHandler { + return try await getCourseProgressHandler(courseID) + } + fatalError("getCourseProgressHandler returns can't have a default value thus its handler must be set") + } + + private let getCourseProgressOfflineState = MockoloMutex(MockoloHandlerState CourseProgressDetails>()) + public var getCourseProgressOfflineCallCount: Int { + return getCourseProgressOfflineState.withLock(\.callCount) + } + public var getCourseProgressOfflineHandler: (@Sendable (String) async throws -> CourseProgressDetails)? { + get { getCourseProgressOfflineState.withLock(\.handler) } + set { getCourseProgressOfflineState.withLock { $0.handler = newValue } } + } + public func getCourseProgressOffline(courseID: String) async throws -> CourseProgressDetails { + let getCourseProgressOfflineHandler = getCourseProgressOfflineState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseProgressOfflineHandler = getCourseProgressOfflineHandler { + return try await getCourseProgressOfflineHandler(courseID) + } + fatalError("getCourseProgressOfflineHandler returns can't have a default value thus its handler must be set") + } +} + +public final class PlayerViewControllerHolderProtocolMock: PlayerViewControllerHolderProtocol, @unchecked Sendable { + private var _appStorage: CoreStorage! + private var _pipManager: PipManagerProtocol! + private var _playerDelegate: PlayerDelegateProtocol! + private var _playerService: PlayerServiceProtocol! + private var _playerTracker: (any PlayerTrackerProtocol)! + public init() { } + public init(url: URL? = nil, blockID: String = "", courseID: String = "", selectedCourseTab: Int = 0, playerController: PlayerControllerProtocol? = nil, isPlaying: Bool = false, isPlayingInPip: Bool = false, isOtherPlayerInPipPlaying: Bool = false, duration: TimeInterval = 0.0) { + self.url = url + self.blockID = blockID + self.courseID = courseID + self.selectedCourseTab = selectedCourseTab + self.playerController = playerController + self.isPlaying = isPlaying + self.isPlayingInPip = isPlayingInPip + self.isOtherPlayerInPipPlaying = isOtherPlayerInPipPlaying + self.duration = duration + } + required public init(url: URL? = nil, blockID: String = "", courseID: String = "", selectedCourseTab: Int = 0, pipManager: PipManagerProtocol, playerTracker: any PlayerTrackerProtocol, playerDelegate: PlayerDelegateProtocol? = nil, playerService: PlayerServiceProtocol, appStorage: CoreStorage? = nil) { + self.url = url + self.blockID = blockID + self.courseID = courseID + self.selectedCourseTab = selectedCourseTab + self._pipManager = pipManager + self._playerTracker = playerTracker + self._playerDelegate = playerDelegate + self._playerService = playerService + self._appStorage = appStorage + } + + + + public var url: URL? = nil + + + public var blockID: String = "" + + + public var courseID: String = "" + + + public var selectedCourseTab: Int = 0 + + + public var playerController: PlayerControllerProtocol? = nil + + + public var isPlaying: Bool = false + + + public var isPlayingInPip: Bool = false + + + public var isOtherPlayerInPipPlaying: Bool = false + + + public var duration: TimeInterval = 0.0 + + private let getTimePublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var getTimePublisherCallCount: Int { + return getTimePublisherState.withLock(\.callCount) + } + public var getTimePublisherHandler: (@Sendable () -> AnyPublisher)? { + get { getTimePublisherState.withLock(\.handler) } + set { getTimePublisherState.withLock { $0.handler = newValue } } + } + public func getTimePublisher() -> AnyPublisher { + let getTimePublisherHandler = getTimePublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getTimePublisherHandler = getTimePublisherHandler { + return getTimePublisherHandler() + } + fatalError("getTimePublisherHandler returns can't have a default value thus its handler must be set") + } + + private let getErrorPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var getErrorPublisherCallCount: Int { + return getErrorPublisherState.withLock(\.callCount) + } + public var getErrorPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { getErrorPublisherState.withLock(\.handler) } + set { getErrorPublisherState.withLock { $0.handler = newValue } } + } + public func getErrorPublisher() -> AnyPublisher { + let getErrorPublisherHandler = getErrorPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getErrorPublisherHandler = getErrorPublisherHandler { + return getErrorPublisherHandler() + } + fatalError("getErrorPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let getRatePublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var getRatePublisherCallCount: Int { + return getRatePublisherState.withLock(\.callCount) + } + public var getRatePublisherHandler: (@Sendable () -> AnyPublisher)? { + get { getRatePublisherState.withLock(\.handler) } + set { getRatePublisherState.withLock { $0.handler = newValue } } + } + public func getRatePublisher() -> AnyPublisher { + let getRatePublisherHandler = getRatePublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getRatePublisherHandler = getRatePublisherHandler { + return getRatePublisherHandler() + } + fatalError("getRatePublisherHandler returns can't have a default value thus its handler must be set") + } + + private let getReadyPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var getReadyPublisherCallCount: Int { + return getReadyPublisherState.withLock(\.callCount) + } + public var getReadyPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { getReadyPublisherState.withLock(\.handler) } + set { getReadyPublisherState.withLock { $0.handler = newValue } } + } + public func getReadyPublisher() -> AnyPublisher { + let getReadyPublisherHandler = getReadyPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getReadyPublisherHandler = getReadyPublisherHandler { + return getReadyPublisherHandler() + } + fatalError("getReadyPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let getFinishPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var getFinishPublisherCallCount: Int { + return getFinishPublisherState.withLock(\.callCount) + } + public var getFinishPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { getFinishPublisherState.withLock(\.handler) } + set { getFinishPublisherState.withLock { $0.handler = newValue } } + } + public func getFinishPublisher() -> AnyPublisher { + let getFinishPublisherHandler = getFinishPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getFinishPublisherHandler = getFinishPublisherHandler { + return getFinishPublisherHandler() + } + fatalError("getFinishPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let getServiceState = MockoloMutex(MockoloHandlerState PlayerServiceProtocol>()) + public var getServiceCallCount: Int { + return getServiceState.withLock(\.callCount) + } + public var getServiceHandler: (@Sendable () -> PlayerServiceProtocol)? { + get { getServiceState.withLock(\.handler) } + set { getServiceState.withLock { $0.handler = newValue } } + } + public func getService() -> PlayerServiceProtocol { + let getServiceHandler = getServiceState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getServiceHandler = getServiceHandler { + return getServiceHandler() + } + fatalError("getServiceHandler returns can't have a default value thus its handler must be set") + } + + private let sendCompletionState = MockoloMutex(MockoloHandlerState ()>()) + public var sendCompletionCallCount: Int { + return sendCompletionState.withLock(\.callCount) + } + public var sendCompletionHandler: (@Sendable () async -> ())? { + get { sendCompletionState.withLock(\.handler) } + set { sendCompletionState.withLock { $0.handler = newValue } } + } + public func sendCompletion() async { + let sendCompletionHandler = sendCompletionState.withLock { state in + state.callCount += 1 + return state.handler + } + if let sendCompletionHandler = sendCompletionHandler { + await sendCompletionHandler() + } + + } +} + +public final class ConnectivityProtocolMock: ConnectivityProtocol, @unchecked Sendable { + public init() { } + public init(isInternetAvaliable: Bool = false, isMobileData: Bool = false) { + self.isInternetAvaliable = isInternetAvaliable + self.isMobileData = isMobileData + } + + + + public var isInternetAvaliable: Bool = false + + + public var isMobileData: Bool = false + + + private var _internetReachableSubject: CurrentValueSubject! + public var internetReachableSubject: CurrentValueSubject { + get { return _internetReachableSubject } + set { _internetReachableSubject = newValue } + } +} + +public final class CourseAnalyticsMock: CourseAnalytics { + public init() { } + + + public private(set) var resumeCourseClickedCallCount = 0 + public var resumeCourseClickedHandler: ((String, String, String) -> ())? + public func resumeCourseClicked(courseId: String, courseName: String, blockId: String) { + resumeCourseClickedCallCount += 1 + if let resumeCourseClickedHandler = resumeCourseClickedHandler { + resumeCourseClickedHandler(courseId, courseName, blockId) + } + + } + + public private(set) var sequentialClickedCallCount = 0 + public var sequentialClickedHandler: ((String, String, String, String) -> ())? + public func sequentialClicked(courseId: String, courseName: String, blockId: String, blockName: String) { + sequentialClickedCallCount += 1 + if let sequentialClickedHandler = sequentialClickedHandler { + sequentialClickedHandler(courseId, courseName, blockId, blockName) + } + + } + + public private(set) var verticalClickedCallCount = 0 + public var verticalClickedHandler: ((String, String, String, String) -> ())? + public func verticalClicked(courseId: String, courseName: String, blockId: String, blockName: String) { + verticalClickedCallCount += 1 + if let verticalClickedHandler = verticalClickedHandler { + verticalClickedHandler(courseId, courseName, blockId, blockName) + } + + } + + public private(set) var nextBlockClickedCallCount = 0 + public var nextBlockClickedHandler: ((String, String, String, String) -> ())? + public func nextBlockClicked(courseId: String, courseName: String, blockId: String, blockName: String) { + nextBlockClickedCallCount += 1 + if let nextBlockClickedHandler = nextBlockClickedHandler { + nextBlockClickedHandler(courseId, courseName, blockId, blockName) + } + + } + + public private(set) var prevBlockClickedCallCount = 0 + public var prevBlockClickedHandler: ((String, String, String, String) -> ())? + public func prevBlockClicked(courseId: String, courseName: String, blockId: String, blockName: String) { + prevBlockClickedCallCount += 1 + if let prevBlockClickedHandler = prevBlockClickedHandler { + prevBlockClickedHandler(courseId, courseName, blockId, blockName) + } + + } + + public private(set) var finishVerticalClickedCallCount = 0 + public var finishVerticalClickedHandler: ((String, String, String, String) -> ())? + public func finishVerticalClicked(courseId: String, courseName: String, blockId: String, blockName: String) { + finishVerticalClickedCallCount += 1 + if let finishVerticalClickedHandler = finishVerticalClickedHandler { + finishVerticalClickedHandler(courseId, courseName, blockId, blockName) + } + + } + + public private(set) var finishVerticalNextSectionClickedCallCount = 0 + public var finishVerticalNextSectionClickedHandler: ((String, String, String, String) -> ())? + public func finishVerticalNextSectionClicked(courseId: String, courseName: String, blockId: String, blockName: String) { + finishVerticalNextSectionClickedCallCount += 1 + if let finishVerticalNextSectionClickedHandler = finishVerticalNextSectionClickedHandler { + finishVerticalNextSectionClickedHandler(courseId, courseName, blockId, blockName) + } + + } + + public private(set) var finishVerticalBackToOutlineClickedCallCount = 0 + public var finishVerticalBackToOutlineClickedHandler: ((String, String) -> ())? + public func finishVerticalBackToOutlineClicked(courseId: String, courseName: String) { + finishVerticalBackToOutlineClickedCallCount += 1 + if let finishVerticalBackToOutlineClickedHandler = finishVerticalBackToOutlineClickedHandler { + finishVerticalBackToOutlineClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseOutlineCourseTabClickedCallCount = 0 + public var courseOutlineCourseTabClickedHandler: ((String, String) -> ())? + public func courseOutlineCourseTabClicked(courseId: String, courseName: String) { + courseOutlineCourseTabClickedCallCount += 1 + if let courseOutlineCourseTabClickedHandler = courseOutlineCourseTabClickedHandler { + courseOutlineCourseTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseOutlineContentTabClickedCallCount = 0 + public var courseOutlineContentTabClickedHandler: ((String, String) -> ())? + public func courseOutlineContentTabClicked(courseId: String, courseName: String) { + courseOutlineContentTabClickedCallCount += 1 + if let courseOutlineContentTabClickedHandler = courseOutlineContentTabClickedHandler { + courseOutlineContentTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseOutlineProgressTabClickedCallCount = 0 + public var courseOutlineProgressTabClickedHandler: ((String, String) -> ())? + public func courseOutlineProgressTabClicked(courseId: String, courseName: String) { + courseOutlineProgressTabClickedCallCount += 1 + if let courseOutlineProgressTabClickedHandler = courseOutlineProgressTabClickedHandler { + courseOutlineProgressTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseOutlineVideosTabClickedCallCount = 0 + public var courseOutlineVideosTabClickedHandler: ((String, String) -> ())? + public func courseOutlineVideosTabClicked(courseId: String, courseName: String) { + courseOutlineVideosTabClickedCallCount += 1 + if let courseOutlineVideosTabClickedHandler = courseOutlineVideosTabClickedHandler { + courseOutlineVideosTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseOutlineOfflineTabClickedCallCount = 0 + public var courseOutlineOfflineTabClickedHandler: ((String, String) -> ())? + public func courseOutlineOfflineTabClicked(courseId: String, courseName: String) { + courseOutlineOfflineTabClickedCallCount += 1 + if let courseOutlineOfflineTabClickedHandler = courseOutlineOfflineTabClickedHandler { + courseOutlineOfflineTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseOutlineDatesTabClickedCallCount = 0 + public var courseOutlineDatesTabClickedHandler: ((String, String) -> ())? + public func courseOutlineDatesTabClicked(courseId: String, courseName: String) { + courseOutlineDatesTabClickedCallCount += 1 + if let courseOutlineDatesTabClickedHandler = courseOutlineDatesTabClickedHandler { + courseOutlineDatesTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseOutlineDiscussionTabClickedCallCount = 0 + public var courseOutlineDiscussionTabClickedHandler: ((String, String) -> ())? + public func courseOutlineDiscussionTabClicked(courseId: String, courseName: String) { + courseOutlineDiscussionTabClickedCallCount += 1 + if let courseOutlineDiscussionTabClickedHandler = courseOutlineDiscussionTabClickedHandler { + courseOutlineDiscussionTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseOutlineHandoutsTabClickedCallCount = 0 + public var courseOutlineHandoutsTabClickedHandler: ((String, String) -> ())? + public func courseOutlineHandoutsTabClicked(courseId: String, courseName: String) { + courseOutlineHandoutsTabClickedCallCount += 1 + if let courseOutlineHandoutsTabClickedHandler = courseOutlineHandoutsTabClickedHandler { + courseOutlineHandoutsTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseOutlineAssignmentsTabClickedCallCount = 0 + public var courseOutlineAssignmentsTabClickedHandler: ((String, String) -> ())? + public func courseOutlineAssignmentsTabClicked(courseId: String, courseName: String) { + courseOutlineAssignmentsTabClickedCallCount += 1 + if let courseOutlineAssignmentsTabClickedHandler = courseOutlineAssignmentsTabClickedHandler { + courseOutlineAssignmentsTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseContentAllTabClickedCallCount = 0 + public var courseContentAllTabClickedHandler: ((String, String) -> ())? + public func courseContentAllTabClicked(courseId: String, courseName: String) { + courseContentAllTabClickedCallCount += 1 + if let courseContentAllTabClickedHandler = courseContentAllTabClickedHandler { + courseContentAllTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseContentVideosTabClickedCallCount = 0 + public var courseContentVideosTabClickedHandler: ((String, String) -> ())? + public func courseContentVideosTabClicked(courseId: String, courseName: String) { + courseContentVideosTabClickedCallCount += 1 + if let courseContentVideosTabClickedHandler = courseContentVideosTabClickedHandler { + courseContentVideosTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseContentAssignmentsTabClickedCallCount = 0 + public var courseContentAssignmentsTabClickedHandler: ((String, String) -> ())? + public func courseContentAssignmentsTabClicked(courseId: String, courseName: String) { + courseContentAssignmentsTabClickedCallCount += 1 + if let courseContentAssignmentsTabClickedHandler = courseContentAssignmentsTabClickedHandler { + courseContentAssignmentsTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseVideoClickedCallCount = 0 + public var courseVideoClickedHandler: ((String, String, String, String) -> ())? + public func courseVideoClicked(courseId: String, courseName: String, blockId: String, blockName: String) { + courseVideoClickedCallCount += 1 + if let courseVideoClickedHandler = courseVideoClickedHandler { + courseVideoClickedHandler(courseId, courseName, blockId, blockName) + } + + } + + public private(set) var courseAssignmentClickedCallCount = 0 + public var courseAssignmentClickedHandler: ((String, String, String, String) -> ())? + public func courseAssignmentClicked(courseId: String, courseName: String, blockId: String, blockName: String) { + courseAssignmentClickedCallCount += 1 + if let courseAssignmentClickedHandler = courseAssignmentClickedHandler { + courseAssignmentClickedHandler(courseId, courseName, blockId, blockName) + } + + } + + public private(set) var contentPageSectionClickedCallCount = 0 + public var contentPageSectionClickedHandler: ((String, String, String, String) -> ())? + public func contentPageSectionClicked(courseId: String, courseName: String, blockId: String, blockName: String) { + contentPageSectionClickedCallCount += 1 + if let contentPageSectionClickedHandler = contentPageSectionClickedHandler { + contentPageSectionClickedHandler(courseId, courseName, blockId, blockName) + } + + } + + public private(set) var contentPageShowCompletedSubsectionClickedCallCount = 0 + public var contentPageShowCompletedSubsectionClickedHandler: ((String, String) -> ())? + public func contentPageShowCompletedSubsectionClicked(courseId: String, courseName: String) { + contentPageShowCompletedSubsectionClickedCallCount += 1 + if let contentPageShowCompletedSubsectionClickedHandler = contentPageShowCompletedSubsectionClickedHandler { + contentPageShowCompletedSubsectionClickedHandler(courseId, courseName) + } + + } + + public private(set) var progressTabClickedCallCount = 0 + public var progressTabClickedHandler: ((String, String) -> ())? + public func progressTabClicked(courseId: String, courseName: String) { + progressTabClickedCallCount += 1 + if let progressTabClickedHandler = progressTabClickedHandler { + progressTabClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseHomeViewAllContentClickedCallCount = 0 + public var courseHomeViewAllContentClickedHandler: ((String, String) -> ())? + public func courseHomeViewAllContentClicked(courseId: String, courseName: String) { + courseHomeViewAllContentClickedCallCount += 1 + if let courseHomeViewAllContentClickedHandler = courseHomeViewAllContentClickedHandler { + courseHomeViewAllContentClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseHomeVideoClickedCallCount = 0 + public var courseHomeVideoClickedHandler: ((String, String, String, String) -> ())? + public func courseHomeVideoClicked(courseId: String, courseName: String, blockId: String, blockName: String) { + courseHomeVideoClickedCallCount += 1 + if let courseHomeVideoClickedHandler = courseHomeVideoClickedHandler { + courseHomeVideoClickedHandler(courseId, courseName, blockId, blockName) + } + + } + + public private(set) var courseHomeViewAllVideosClickedCallCount = 0 + public var courseHomeViewAllVideosClickedHandler: ((String, String) -> ())? + public func courseHomeViewAllVideosClicked(courseId: String, courseName: String) { + courseHomeViewAllVideosClickedCallCount += 1 + if let courseHomeViewAllVideosClickedHandler = courseHomeViewAllVideosClickedHandler { + courseHomeViewAllVideosClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseHomeAssignmentClickedCallCount = 0 + public var courseHomeAssignmentClickedHandler: ((String, String, String, String) -> ())? + public func courseHomeAssignmentClicked(courseId: String, courseName: String, blockId: String, blockName: String) { + courseHomeAssignmentClickedCallCount += 1 + if let courseHomeAssignmentClickedHandler = courseHomeAssignmentClickedHandler { + courseHomeAssignmentClickedHandler(courseId, courseName, blockId, blockName) + } + + } + + public private(set) var courseHomeViewAllAssignmentsClickedCallCount = 0 + public var courseHomeViewAllAssignmentsClickedHandler: ((String, String) -> ())? + public func courseHomeViewAllAssignmentsClicked(courseId: String, courseName: String) { + courseHomeViewAllAssignmentsClickedCallCount += 1 + if let courseHomeViewAllAssignmentsClickedHandler = courseHomeViewAllAssignmentsClickedHandler { + courseHomeViewAllAssignmentsClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseHomeGradesViewProgressClickedCallCount = 0 + public var courseHomeGradesViewProgressClickedHandler: ((String, String) -> ())? + public func courseHomeGradesViewProgressClicked(courseId: String, courseName: String) { + courseHomeGradesViewProgressClickedCallCount += 1 + if let courseHomeGradesViewProgressClickedHandler = courseHomeGradesViewProgressClickedHandler { + courseHomeGradesViewProgressClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseHomeSectionSubsectionClickCallCount = 0 + public var courseHomeSectionSubsectionClickHandler: ((String, String, String, String) -> ())? + public func courseHomeSectionSubsectionClick(courseId: String, courseName: String, courseSection: String, courseSubsection: String) { + courseHomeSectionSubsectionClickCallCount += 1 + if let courseHomeSectionSubsectionClickHandler = courseHomeSectionSubsectionClickHandler { + courseHomeSectionSubsectionClickHandler(courseId, courseName, courseSection, courseSubsection) + } + + } + + public private(set) var datesComponentTappedCallCount = 0 + public var datesComponentTappedHandler: ((String, String, String, Bool) -> ())? + public func datesComponentTapped(courseId: String, blockId: String, link: String, supported: Bool) { + datesComponentTappedCallCount += 1 + if let datesComponentTappedHandler = datesComponentTappedHandler { + datesComponentTappedHandler(courseId, blockId, link, supported) + } + + } + + public private(set) var calendarSyncToggleCallCount = 0 + public var calendarSyncToggleHandler: ((EnrollmentMode, CoursePacing, String, CalendarDialogueAction) -> ())? + public func calendarSyncToggle(enrollmentMode: EnrollmentMode, pacing: CoursePacing, courseId: String, action: CalendarDialogueAction) { + calendarSyncToggleCallCount += 1 + if let calendarSyncToggleHandler = calendarSyncToggleHandler { + calendarSyncToggleHandler(enrollmentMode, pacing, courseId, action) + } + + } + + public private(set) var calendarSyncDialogActionCallCount = 0 + public var calendarSyncDialogActionHandler: ((EnrollmentMode, CoursePacing, String, CalendarDialogueType, CalendarDialogueAction) -> ())? + public func calendarSyncDialogAction(enrollmentMode: EnrollmentMode, pacing: CoursePacing, courseId: String, dialog: CalendarDialogueType, action: CalendarDialogueAction) { + calendarSyncDialogActionCallCount += 1 + if let calendarSyncDialogActionHandler = calendarSyncDialogActionHandler { + calendarSyncDialogActionHandler(enrollmentMode, pacing, courseId, dialog, action) + } + + } + + public private(set) var calendarSyncSnackbarCallCount = 0 + public var calendarSyncSnackbarHandler: ((EnrollmentMode, CoursePacing, String, SnackbarType) -> ())? + public func calendarSyncSnackbar(enrollmentMode: EnrollmentMode, pacing: CoursePacing, courseId: String, snackbar: SnackbarType) { + calendarSyncSnackbarCallCount += 1 + if let calendarSyncSnackbarHandler = calendarSyncSnackbarHandler { + calendarSyncSnackbarHandler(enrollmentMode, pacing, courseId, snackbar) + } + + } + + public private(set) var trackCourseEventCallCount = 0 + public var trackCourseEventHandler: ((AnalyticsEvent, EventBIValue, String) -> ())? + public func trackCourseEvent(_ event: AnalyticsEvent, biValue: EventBIValue, courseID: String) { + trackCourseEventCallCount += 1 + if let trackCourseEventHandler = trackCourseEventHandler { + trackCourseEventHandler(event, biValue, courseID) + } + + } + + public private(set) var trackCourseScreenEventCallCount = 0 + public var trackCourseScreenEventHandler: ((AnalyticsEvent, EventBIValue, String) -> ())? + public func trackCourseScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, courseID: String) { + trackCourseScreenEventCallCount += 1 + if let trackCourseScreenEventHandler = trackCourseScreenEventHandler { + trackCourseScreenEventHandler(event, biValue, courseID) + } + + } + + public private(set) var plsEventCallCount = 0 + public var plsEventHandler: ((AnalyticsEvent, EventBIValue, String, String, String) -> ())? + public func plsEvent(_ event: AnalyticsEvent, bivalue: EventBIValue, courseID: String, screenName: String, type: String) { + plsEventCallCount += 1 + if let plsEventHandler = plsEventHandler { + plsEventHandler(event, bivalue, courseID, screenName, type) + } + + } + + public private(set) var plsSuccessEventCallCount = 0 + public var plsSuccessEventHandler: ((AnalyticsEvent, EventBIValue, String, String, String, Bool) -> ())? + public func plsSuccessEvent(_ event: AnalyticsEvent, bivalue: EventBIValue, courseID: String, screenName: String, type: String, success: Bool) { + plsSuccessEventCallCount += 1 + if let plsSuccessEventHandler = plsSuccessEventHandler { + plsSuccessEventHandler(event, bivalue, courseID, screenName, type, success) + } + + } + + public private(set) var bulkDownloadVideosToggleCallCount = 0 + public var bulkDownloadVideosToggleHandler: ((String, Bool) -> ())? + public func bulkDownloadVideosToggle(courseID: String, action: Bool) { + bulkDownloadVideosToggleCallCount += 1 + if let bulkDownloadVideosToggleHandler = bulkDownloadVideosToggleHandler { + bulkDownloadVideosToggleHandler(courseID, action) + } + + } + + public private(set) var bulkDownloadVideosSubsectionCallCount = 0 + public var bulkDownloadVideosSubsectionHandler: ((String, String, String, Int) -> ())? + public func bulkDownloadVideosSubsection(courseID: String, sectionID: String, subSectionID: String, videos: Int) { + bulkDownloadVideosSubsectionCallCount += 1 + if let bulkDownloadVideosSubsectionHandler = bulkDownloadVideosSubsectionHandler { + bulkDownloadVideosSubsectionHandler(courseID, sectionID, subSectionID, videos) + } + + } + + public private(set) var bulkDeleteVideosSubsectionCallCount = 0 + public var bulkDeleteVideosSubsectionHandler: ((String, String, Int) -> ())? + public func bulkDeleteVideosSubsection(courseID: String, subSectionID: String, videos: Int) { + bulkDeleteVideosSubsectionCallCount += 1 + if let bulkDeleteVideosSubsectionHandler = bulkDeleteVideosSubsectionHandler { + bulkDeleteVideosSubsectionHandler(courseID, subSectionID, videos) + } + + } + + public private(set) var bulkDownloadVideosSectionCallCount = 0 + public var bulkDownloadVideosSectionHandler: ((String, String, Int) -> ())? + public func bulkDownloadVideosSection(courseID: String, sectionID: String, videos: Int) { + bulkDownloadVideosSectionCallCount += 1 + if let bulkDownloadVideosSectionHandler = bulkDownloadVideosSectionHandler { + bulkDownloadVideosSectionHandler(courseID, sectionID, videos) + } + + } + + public private(set) var bulkDeleteVideosSectionCallCount = 0 + public var bulkDeleteVideosSectionHandler: ((String, String, Int) -> ())? + public func bulkDeleteVideosSection(courseID: String, sectionId: String, videos: Int) { + bulkDeleteVideosSectionCallCount += 1 + if let bulkDeleteVideosSectionHandler = bulkDeleteVideosSectionHandler { + bulkDeleteVideosSectionHandler(courseID, sectionId, videos) + } + + } + + public private(set) var videoLoadedCallCount = 0 + public var videoLoadedHandler: ((String, String, String) -> ())? + public func videoLoaded(courseID: String, blockID: String, videoURL: String) { + videoLoadedCallCount += 1 + if let videoLoadedHandler = videoLoadedHandler { + videoLoadedHandler(courseID, blockID, videoURL) + } + + } + + public private(set) var videoPlayedCallCount = 0 + public var videoPlayedHandler: ((String, String, String) -> ())? + public func videoPlayed(courseID: String, blockID: String, videoURL: String) { + videoPlayedCallCount += 1 + if let videoPlayedHandler = videoPlayedHandler { + videoPlayedHandler(courseID, blockID, videoURL) + } + + } + + public private(set) var videoSpeedChangeCallCount = 0 + public var videoSpeedChangeHandler: ((String, String, String, Float, Float, Double, Double) -> ())? + public func videoSpeedChange(courseID: String, blockID: String, videoURL: String, oldSpeed: Float, newSpeed: Float, currentTime: Double, duration: Double) { + videoSpeedChangeCallCount += 1 + if let videoSpeedChangeHandler = videoSpeedChangeHandler { + videoSpeedChangeHandler(courseID, blockID, videoURL, oldSpeed, newSpeed, currentTime, duration) + } + + } + + public private(set) var videoPausedCallCount = 0 + public var videoPausedHandler: ((String, String, String, Double, Double) -> ())? + public func videoPaused(courseID: String, blockID: String, videoURL: String, currentTime: Double, duration: Double) { + videoPausedCallCount += 1 + if let videoPausedHandler = videoPausedHandler { + videoPausedHandler(courseID, blockID, videoURL, currentTime, duration) + } + + } + + public private(set) var videoCompletedCallCount = 0 + public var videoCompletedHandler: ((String, String, String, Double, Double) -> ())? + public func videoCompleted(courseID: String, blockID: String, videoURL: String, currentTime: Double, duration: Double) { + videoCompletedCallCount += 1 + if let videoCompletedHandler = videoCompletedHandler { + videoCompletedHandler(courseID, blockID, videoURL, currentTime, duration) + } + + } +} + +public final class DownloadManagerProtocolMock: DownloadManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCurrentDownloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var getCurrentDownloadTaskCallCount: Int { + return getCurrentDownloadTaskState.withLock(\.callCount) + } + public var getCurrentDownloadTaskHandler: (@Sendable () async -> DownloadDataTask?)? { + get { getCurrentDownloadTaskState.withLock(\.handler) } + set { getCurrentDownloadTaskState.withLock { $0.handler = newValue } } + } + public func getCurrentDownloadTask() async -> DownloadDataTask? { + let getCurrentDownloadTaskHandler = getCurrentDownloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCurrentDownloadTaskHandler = getCurrentDownloadTaskHandler { + return await getCurrentDownloadTaskHandler() + } + return nil + } + + private let eventPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var eventPublisherCallCount: Int { + return eventPublisherState.withLock(\.callCount) + } + public var eventPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { eventPublisherState.withLock(\.handler) } + set { eventPublisherState.withLock { $0.handler = newValue } } + } + public func eventPublisher() -> AnyPublisher { + let eventPublisherHandler = eventPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let eventPublisherHandler = eventPublisherHandler { + return eventPublisherHandler() + } + fatalError("eventPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([CourseBlock]) async throws -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock]) async throws { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + try await addToDownloadQueueHandler(blocks) + } + + } + + private let getDownloadTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksCallCount: Int { + return getDownloadTasksState.withLock(\.callCount) + } + public var getDownloadTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadTasksState.withLock(\.handler) } + set { getDownloadTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadTasks() async -> [DownloadDataTask] { + let getDownloadTasksHandler = getDownloadTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksHandler = getDownloadTasksHandler { + return await getDownloadTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksForCourseCallCount: Int { + return getDownloadTasksForCourseState.withLock(\.callCount) + } + public var getDownloadTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadTasksForCourseState.withLock(\.handler) } + set { getDownloadTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadTasksForCourseHandler = getDownloadTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksForCourseHandler = getDownloadTasksForCourseHandler { + return await getDownloadTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let cancelDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCallCount: Int { + return cancelDownloadingState.withLock(\.callCount) + } + public var cancelDownloadingHandler: (@Sendable (String, [CourseBlock]) async throws -> ())? { + get { cancelDownloadingState.withLock(\.handler) } + set { cancelDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String, blocks: [CourseBlock]) async throws { + let cancelDownloadingHandler = cancelDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingHandler = cancelDownloadingHandler { + try await cancelDownloadingHandler(courseId, blocks) + } + + } + + private let cancelDownloadingTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingTaskCallCount: Int { + return cancelDownloadingTaskState.withLock(\.callCount) + } + public var cancelDownloadingTaskHandler: (@Sendable (DownloadDataTask) async throws -> ())? { + get { cancelDownloadingTaskState.withLock(\.handler) } + set { cancelDownloadingTaskState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(task: DownloadDataTask) async throws { + let cancelDownloadingTaskHandler = cancelDownloadingTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingTaskHandler = cancelDownloadingTaskHandler { + try await cancelDownloadingTaskHandler(task) + } + + } + + private let cancelDownloadingCourseIdState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCourseIdCallCount: Int { + return cancelDownloadingCourseIdState.withLock(\.callCount) + } + public var cancelDownloadingCourseIdHandler: (@Sendable (String) async throws -> ())? { + get { cancelDownloadingCourseIdState.withLock(\.handler) } + set { cancelDownloadingCourseIdState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String) async throws { + let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdHandler { + try await cancelDownloadingCourseIdHandler(courseId) + } + + } + + private let cancelAllDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelAllDownloadingCallCount: Int { + return cancelAllDownloadingState.withLock(\.callCount) + } + public var cancelAllDownloadingHandler: (@Sendable () async throws -> ())? { + get { cancelAllDownloadingState.withLock(\.handler) } + set { cancelAllDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelAllDownloading() async throws { + let cancelAllDownloadingHandler = cancelAllDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelAllDownloadingHandler = cancelAllDownloadingHandler { + try await cancelAllDownloadingHandler() + } + + } + + private let deleteAllState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllCallCount: Int { + return deleteAllState.withLock(\.callCount) + } + public var deleteAllHandler: (@Sendable () async -> ())? { + get { deleteAllState.withLock(\.handler) } + set { deleteAllState.withLock { $0.handler = newValue } } + } + public func deleteAll() async { + let deleteAllHandler = deleteAllState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllHandler = deleteAllHandler { + await deleteAllHandler() + } + + } + + private let fileUrlState = MockoloMutex(MockoloHandlerState URL?>()) + public var fileUrlCallCount: Int { + return fileUrlState.withLock(\.callCount) + } + public var fileUrlHandler: (@Sendable (String) async -> URL?)? { + get { fileUrlState.withLock(\.handler) } + set { fileUrlState.withLock { $0.handler = newValue } } + } + public func fileUrl(for blockId: String) async -> URL? { + let fileUrlHandler = fileUrlState.withLock { state in + state.callCount += 1 + return state.handler + } + if let fileUrlHandler = fileUrlHandler { + return await fileUrlHandler(blockId) + } + return nil + } + + private let resumeDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var resumeDownloadingCallCount: Int { + return resumeDownloadingState.withLock(\.callCount) + } + public var resumeDownloadingHandler: (@Sendable () async throws -> ())? { + get { resumeDownloadingState.withLock(\.handler) } + set { resumeDownloadingState.withLock { $0.handler = newValue } } + } + public func resumeDownloading() async throws { + let resumeDownloadingHandler = resumeDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resumeDownloadingHandler = resumeDownloadingHandler { + try await resumeDownloadingHandler() + } + + } + + private let isLargeVideosSizeState = MockoloMutex(MockoloHandlerState Bool>()) + public var isLargeVideosSizeCallCount: Int { + return isLargeVideosSizeState.withLock(\.callCount) + } + public var isLargeVideosSizeHandler: (@Sendable ([CourseBlock]) async -> Bool)? { + get { isLargeVideosSizeState.withLock(\.handler) } + set { isLargeVideosSizeState.withLock { $0.handler = newValue } } + } + public func isLargeVideosSize(blocks: [CourseBlock]) async -> Bool { + let isLargeVideosSizeHandler = isLargeVideosSizeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isLargeVideosSizeHandler = isLargeVideosSizeHandler { + return await isLargeVideosSizeHandler(blocks) + } + return false + } + + private let removeAppSupportDirectoryUnusedContentState = MockoloMutex(MockoloHandlerState ()>()) + public var removeAppSupportDirectoryUnusedContentCallCount: Int { + return removeAppSupportDirectoryUnusedContentState.withLock(\.callCount) + } + public var removeAppSupportDirectoryUnusedContentHandler: (@Sendable () -> ())? { + get { removeAppSupportDirectoryUnusedContentState.withLock(\.handler) } + set { removeAppSupportDirectoryUnusedContentState.withLock { $0.handler = newValue } } + } + public func removeAppSupportDirectoryUnusedContent() { + let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentHandler { + removeAppSupportDirectoryUnusedContentHandler() + } + + } + + private let deleteState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteCallCount: Int { + return deleteState.withLock(\.callCount) + } + public var deleteHandler: (@Sendable ([CourseBlock], String) async -> ())? { + get { deleteState.withLock(\.handler) } + set { deleteState.withLock { $0.handler = newValue } } + } + public func delete(blocks: [CourseBlock], courseId: String) async { + let deleteHandler = deleteState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteHandler = deleteHandler { + await deleteHandler(blocks, courseId) + } + + } + + private let downloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadTaskCallCount: Int { + return downloadTaskState.withLock(\.callCount) + } + public var downloadTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadTaskState.withLock(\.handler) } + set { downloadTaskState.withLock { $0.handler = newValue } } + } + public func downloadTask(for blockId: String) async -> DownloadDataTask? { + let downloadTaskHandler = downloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadTaskHandler = downloadTaskHandler { + return await downloadTaskHandler(blockId) + } + return nil + } + + private let getFreeDiskSpaceState = MockoloMutex(MockoloHandlerState Int?>()) + public var getFreeDiskSpaceCallCount: Int { + return getFreeDiskSpaceState.withLock(\.callCount) + } + public var getFreeDiskSpaceHandler: (@Sendable () -> Int?)? { + get { getFreeDiskSpaceState.withLock(\.handler) } + set { getFreeDiskSpaceState.withLock { $0.handler = newValue } } + } + public func getFreeDiskSpace() -> Int? { + let getFreeDiskSpaceHandler = getFreeDiskSpaceState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getFreeDiskSpaceHandler = getFreeDiskSpaceHandler { + return getFreeDiskSpaceHandler() + } + return nil + } +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { + print("At \(function), the captured arguments are not Sendable, it is not concurrency-safe.") +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { +} + +/// Will be replaced to `Synchronization.Mutex` in future. +fileprivate final class MockoloMutex: @unchecked Sendable { + private let lock = NSLock() + private var value: Value + init(_ initialValue: Value) { + self.value = initialValue + } +#if compiler(>=6.0) + borrowing func withLock(_ body: (inout sending Value) throws(E) -> Result) throws(E) -> sending Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#else + func withLock(_ body: (inout Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#endif +} + +fileprivate struct MockoloUnsafeTransfer: @unchecked Sendable { + var value: Value + init(_ value: Value) { + self.value = value + } +} + +fileprivate struct MockoloHandlerState { + var argValues: [MockoloUnsafeTransfer] = [] + var handler: Handler? = nil + var callCount: Int = 0 +} + diff --git a/Course/CourseTests/Presentation/Container/CourseContainerViewModelTests.swift b/Course/CourseTests/Presentation/Container/CourseContainerViewModelTests.swift index 9860fab16..6381232fa 100644 --- a/Course/CourseTests/Presentation/Container/CourseContainerViewModelTests.swift +++ b/Course/CourseTests/Presentation/Container/CourseContainerViewModelTests.swift @@ -2,10 +2,9 @@ // CourseContainerViewModelTests.swift // CourseTests // -// Created by  Stepanok Ivan on 20.01.2023. +// Created by Stepanok Ivan on 20.01.2023. // -import SwiftyMocky import XCTest import Core @testable import Course @@ -16,13 +15,13 @@ import Combine @MainActor final class CourseContainerViewModelTests: XCTestCase { var courseHelperMock: CourseDownloadHelperProtocolMock! - + override func setUpWithError() throws { try super.setUpWithError() courseHelperMock = CourseDownloadHelperProtocolMock() - Given(courseHelperMock, .publisher(willReturn: Just(.empty).eraseToAnyPublisher())) + courseHelperMock.publisherHandler = { Just(.empty).eraseToAnyPublisher() } } - + func testGetCourseBlocksSuccess() async throws { let interactor = CourseInteractorProtocolMock() let authInteractor = AuthInteractorProtocolMock() @@ -30,9 +29,11 @@ final class CourseContainerViewModelTests: XCTestCase { let analytics = CourseAnalyticsMock() let config = ConfigMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) + + connectivity.isInternetAvaliable = true + connectivity.internetReachableSubject = .init(.reachable) + + let downloadManager = DownloadManagerMock() let viewModel = CourseContainerViewModel( interactor: interactor, @@ -41,7 +42,7 @@ final class CourseContainerViewModelTests: XCTestCase { analytics: analytics, config: config, connectivity: connectivity, - manager: DownloadManagerMock(), + manager: downloadManager, storage: CourseStorageMock(), isActive: true, courseStart: Date(), @@ -52,13 +53,13 @@ final class CourseContainerViewModelTests: XCTestCase { coreAnalytics: CoreAnalyticsMock(), courseHelper: courseHelperMock ) - + let block = CourseBlock( blockId: "", id: "", courseId: "123", topicId: "", - graded: true, + graded: true, due: Date(), completion: 0, type: .problem, @@ -66,7 +67,7 @@ final class CourseContainerViewModelTests: XCTestCase { studentUrl: "", webUrl: "", encodedVideo: nil, - multiDevice: true, + multiDevice: true, offlineDownload: nil ) let vertical = CourseVertical( @@ -85,7 +86,7 @@ final class CourseContainerViewModelTests: XCTestCase { displayName: "", type: .chapter, completion: 0, - childs: [vertical], + childs: [vertical], sequentialProgress: nil, due: Date() ) @@ -96,9 +97,9 @@ final class CourseContainerViewModelTests: XCTestCase { type: .chapter, childs: [sequential] ) - + let childs = [chapter] - + let courseStructure = CourseStructure( id: "123", graded: true, @@ -120,20 +121,14 @@ final class CourseContainerViewModelTests: XCTestCase { isSelfPaced: true, courseProgress: nil ) - + let resumeBlock = ResumeBlock(blockID: "123") - - Given(interactor, .getCourseBlocks(courseID: "123", - willReturn: courseStructure)) - Given(interactor, .getCourseBlocks(courseID: "123", - willReturn: courseStructure)) - Given(interactor, .resumeBlock(courseID: "123", - willReturn: resumeBlock)) - Given(interactor, .getCourseVideoBlocks(fullStructure: .any, - willReturn: courseStructure)) - Given(interactor, .getCourseAssignmentBlocks(fullStructure: .any, - willReturn: courseStructure)) - + + interactor.getCourseBlocksHandler = { _ in courseStructure } + interactor.resumeBlockHandler = { _ in resumeBlock } + interactor.getCourseVideoBlocksHandler = { _ in courseStructure } + interactor.getCourseAssignmentBlocksHandler = { _ in courseStructure } + let mockCourseProgress = CourseProgressDetails( verifiedMode: nil, accessExpiration: nil, @@ -165,20 +160,20 @@ final class CourseContainerViewModelTests: XCTestCase { sectionScores: [], verificationData: nil ) - Given(interactor, .getCourseProgress(courseID: "123", willReturn: mockCourseProgress)) - + interactor.getCourseProgressHandler = { _ in mockCourseProgress } + await viewModel.getCourseBlocks(courseID: "123") - - Verify(interactor, .getCourseBlocks(courseID: .any)) - Verify(interactor, .getCourseVideoBlocks(fullStructure: .any)) - Verify(interactor, .resumeBlock(courseID: "123")) + + XCTAssertTrue(interactor.getCourseBlocksCallCount > 0) + XCTAssertTrue(interactor.getCourseVideoBlocksCallCount > 0) + XCTAssertTrue(interactor.resumeBlockCallCount > 0) XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) XCTAssertEqual(viewModel.courseStructure, courseStructure) XCTAssertEqual(viewModel.courseHelper.courseStructure, courseStructure) } - + func testGetCourseBlocksOfflineSuccess() async throws { let interactor = CourseInteractorProtocolMock() let authInteractor = AuthInteractorProtocolMock() @@ -186,9 +181,11 @@ final class CourseContainerViewModelTests: XCTestCase { let analytics = CourseAnalyticsMock() let config = ConfigMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: false)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) + + connectivity.isInternetAvaliable = false + connectivity.internetReachableSubject = .init(.reachable) + + let downloadManager = DownloadManagerMock() let viewModel = CourseContainerViewModel( interactor: interactor, @@ -197,7 +194,7 @@ final class CourseContainerViewModelTests: XCTestCase { analytics: analytics, config: config, connectivity: connectivity, - manager: DownloadManagerMock(), + manager: downloadManager, storage: CourseStorageMock(), isActive: true, courseStart: Date(), @@ -208,7 +205,7 @@ final class CourseContainerViewModelTests: XCTestCase { coreAnalytics: CoreAnalyticsMock(), courseHelper: courseHelperMock ) - + let courseStructure = CourseStructure( id: "123", graded: true, @@ -230,13 +227,11 @@ final class CourseContainerViewModelTests: XCTestCase { isSelfPaced: true, courseProgress: nil ) - - Given(interactor, .getLoadedCourseBlocks(courseID: .any, willReturn: courseStructure)) - Given(interactor, .getCourseVideoBlocks(fullStructure: .any, - willReturn: courseStructure)) - Given(interactor, .getCourseAssignmentBlocks(fullStructure: .any, - willReturn: courseStructure)) - + + interactor.getLoadedCourseBlocksHandler = { _ in courseStructure } + interactor.getCourseVideoBlocksHandler = { _ in courseStructure } + interactor.getCourseAssignmentBlocksHandler = { _ in courseStructure } + let mockCourseProgress = CourseProgressDetails( verifiedMode: nil, accessExpiration: nil, @@ -268,19 +263,19 @@ final class CourseContainerViewModelTests: XCTestCase { sectionScores: [], verificationData: nil ) - Given(interactor, .getCourseProgressOffline(courseID: "123", willReturn: mockCourseProgress)) - + interactor.getCourseProgressOfflineHandler = { _ in mockCourseProgress } + await viewModel.getCourseBlocks(courseID: "123") - - Verify(interactor, .getLoadedCourseBlocks(courseID: .any)) - Verify(interactor, .getCourseVideoBlocks(fullStructure: .any)) + + XCTAssertTrue(interactor.getLoadedCourseBlocksCallCount > 0) + XCTAssertTrue(interactor.getCourseVideoBlocksCallCount > 0) XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) XCTAssertEqual(viewModel.courseStructure, courseStructure) XCTAssertEqual(viewModel.courseHelper.courseStructure, courseStructure) } - + func testGetCourseBlocksNoInternetError() async throws { let interactor = CourseInteractorProtocolMock() let authInteractor = AuthInteractorProtocolMock() @@ -288,9 +283,11 @@ final class CourseContainerViewModelTests: XCTestCase { let analytics = CourseAnalyticsMock() let config = ConfigMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) + + connectivity.isInternetAvaliable = true + connectivity.internetReachableSubject = .init(.reachable) + + let downloadManager = DownloadManagerMock() let viewModel = CourseContainerViewModel( interactor: interactor, @@ -299,7 +296,7 @@ final class CourseContainerViewModelTests: XCTestCase { analytics: analytics, config: config, connectivity: connectivity, - manager: DownloadManagerMock(), + manager: downloadManager, storage: CourseStorageMock(), isActive: true, courseStart: Date(), @@ -310,9 +307,9 @@ final class CourseContainerViewModelTests: XCTestCase { coreAnalytics: CoreAnalyticsMock(), courseHelper: courseHelperMock ) - + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - + let courseStructure = CourseStructure( id: "123", graded: true, @@ -334,12 +331,10 @@ final class CourseContainerViewModelTests: XCTestCase { isSelfPaced: true, courseProgress: nil ) - - Given(interactor, .getCourseBlocks(courseID: "123", - willThrow: noInternetError)) - Given(interactor, .getCourseAssignmentBlocks(fullStructure: .any, - willReturn: courseStructure)) - + + interactor.getCourseBlocksHandler = { _ in throw noInternetError } + interactor.getCourseAssignmentBlocksHandler = { _ in courseStructure } + let mockCourseProgress = CourseProgressDetails( verifiedMode: nil, accessExpiration: nil, @@ -371,17 +366,17 @@ final class CourseContainerViewModelTests: XCTestCase { sectionScores: [], verificationData: nil ) - Given(interactor, .getCourseProgress(courseID: "123", willReturn: mockCourseProgress)) - + interactor.getCourseProgressHandler = { _ in mockCourseProgress } + await viewModel.getCourseBlocks(courseID: "123") - - Verify(interactor, .getCourseBlocks(courseID: .any)) + + XCTAssertTrue(interactor.getCourseBlocksCallCount > 0) XCTAssertFalse(viewModel.isShowProgress) XCTAssertNil(viewModel.courseStructure) XCTAssertNil(viewModel.courseVideosStructure) XCTAssertNil(viewModel.courseHelper.courseStructure) } - + func testGetCourseBlocksNoCacheError() async throws { let interactor = CourseInteractorProtocolMock() let authInteractor = AuthInteractorProtocolMock() @@ -389,9 +384,11 @@ final class CourseContainerViewModelTests: XCTestCase { let analytics = CourseAnalyticsMock() let config = ConfigMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) + + connectivity.isInternetAvaliable = true + connectivity.internetReachableSubject = .init(.reachable) + + let downloadManager = DownloadManagerMock() let viewModel = CourseContainerViewModel( interactor: interactor, @@ -400,7 +397,7 @@ final class CourseContainerViewModelTests: XCTestCase { analytics: analytics, config: config, connectivity: connectivity, - manager: DownloadManagerMock(), + manager: downloadManager, storage: CourseStorageMock(), isActive: true, courseStart: Date(), @@ -411,7 +408,7 @@ final class CourseContainerViewModelTests: XCTestCase { coreAnalytics: CoreAnalyticsMock(), courseHelper: courseHelperMock ) - + let courseStructure = CourseStructure( id: "123", graded: true, @@ -433,12 +430,10 @@ final class CourseContainerViewModelTests: XCTestCase { isSelfPaced: true, courseProgress: nil ) - - Given(interactor, .getCourseBlocks(courseID: "123", - willThrow: NoCachedDataError())) - Given(interactor, .getCourseAssignmentBlocks(fullStructure: .any, - willReturn: courseStructure)) - + + interactor.getCourseBlocksHandler = { _ in throw NoCachedDataError() } + interactor.getCourseAssignmentBlocksHandler = { _ in courseStructure } + let mockCourseProgress = CourseProgressDetails( verifiedMode: nil, accessExpiration: nil, @@ -470,17 +465,17 @@ final class CourseContainerViewModelTests: XCTestCase { sectionScores: [], verificationData: nil ) - Given(interactor, .getCourseProgress(courseID: "123", willReturn: mockCourseProgress)) - + interactor.getCourseProgressHandler = { _ in mockCourseProgress } + await viewModel.getCourseBlocks(courseID: "123") - - Verify(interactor, .getCourseBlocks(courseID: .any)) + + XCTAssertTrue(interactor.getCourseBlocksCallCount > 0) XCTAssertFalse(viewModel.isShowProgress) XCTAssertNil(viewModel.courseStructure) XCTAssertNil(viewModel.courseVideosStructure) XCTAssertNil(viewModel.courseHelper.courseStructure) } - + func testGetCourseBlocksUnknownError() async throws { let interactor = CourseInteractorProtocolMock() let authInteractor = AuthInteractorProtocolMock() @@ -488,9 +483,11 @@ final class CourseContainerViewModelTests: XCTestCase { let analytics = CourseAnalyticsMock() let config = ConfigMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) + + connectivity.isInternetAvaliable = true + connectivity.internetReachableSubject = .init(.reachable) + + let downloadManager = DownloadManagerMock() let viewModel = CourseContainerViewModel( interactor: interactor, @@ -499,7 +496,7 @@ final class CourseContainerViewModelTests: XCTestCase { analytics: analytics, config: config, connectivity: connectivity, - manager: DownloadManagerMock(), + manager: downloadManager, storage: CourseStorageMock(), isActive: true, courseStart: Date(), @@ -510,7 +507,7 @@ final class CourseContainerViewModelTests: XCTestCase { coreAnalytics: CoreAnalyticsMock(), courseHelper: courseHelperMock ) - + let courseStructure = CourseStructure( id: "123", graded: true, @@ -532,12 +529,10 @@ final class CourseContainerViewModelTests: XCTestCase { isSelfPaced: true, courseProgress: nil ) - - Given(interactor, .getCourseBlocks(courseID: "123", - willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - Given(interactor, .getCourseAssignmentBlocks(fullStructure: .any, - willReturn: courseStructure)) - + + interactor.getCourseBlocksHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + interactor.getCourseAssignmentBlocksHandler = { _ in courseStructure } + let mockCourseProgress = CourseProgressDetails( verifiedMode: nil, accessExpiration: nil, @@ -569,301 +564,29 @@ final class CourseContainerViewModelTests: XCTestCase { sectionScores: [], verificationData: nil ) - Given(interactor, .getCourseProgress(courseID: "123", willReturn: mockCourseProgress)) - + interactor.getCourseProgressHandler = { _ in mockCourseProgress } + await viewModel.getCourseBlocks(courseID: "123") - - Verify(interactor, .getCourseBlocks(courseID: .any)) + + XCTAssertTrue(interactor.getCourseBlocksCallCount > 0) XCTAssertFalse(viewModel.isShowProgress) XCTAssertNil(viewModel.courseStructure) XCTAssertNil(viewModel.courseVideosStructure) XCTAssertNil(viewModel.courseHelper.courseStructure) } - - func testTabSelectedAnalytics() { - let interactor = CourseInteractorProtocolMock() - let authInteractor = AuthInteractorProtocolMock() - let router = CourseRouterMock() - let analytics = CourseAnalyticsMock() - let config = ConfigMock() - let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) - - let viewModel = CourseContainerViewModel( - interactor: interactor, - authInteractor: authInteractor, - router: router, - analytics: analytics, - config: config, - connectivity: connectivity, - manager: DownloadManagerMock(), - storage: CourseStorageMock(), - isActive: true, - courseStart: Date(), - courseEnd: nil, - enrollmentStart: nil, - enrollmentEnd: nil, - lastVisitedBlockID: nil, - coreAnalytics: CoreAnalyticsMock(), - courseHelper: courseHelperMock - ) - - viewModel.trackSelectedTab(selection: .course, courseId: "1", courseName: "name") - Verify(analytics, .courseOutlineCourseTabClicked(courseId: .value("1"), courseName: .value("name"))) - - viewModel.trackSelectedTab(selection: .discussion, courseId: "1", courseName: "name") - Verify(analytics, .courseOutlineDiscussionTabClicked(courseId: .value("1"), courseName: .value("name"))) - - viewModel.trackSelectedTab(selection: .handounds, courseId: "1", courseName: "name") - Verify(analytics, .courseOutlineHandoutsTabClicked(courseId: .value("1"), courseName: .value("name"))) - } - - func testOnDownloadViewAvailableTap() async throws { - let interactor = CourseInteractorProtocolMock() - let authInteractor = AuthInteractorProtocolMock() - let router = CourseRouterMock() - let analytics = CourseAnalyticsMock() - let config = ConfigMock() - let connectivity = ConnectivityProtocolMock() - let downloadManager = DownloadManagerProtocolMock() - - let blockId = "chapter:block:1" - - let block = CourseBlock( - blockId: blockId, - id: "1", - courseId: "123", - topicId: "", - graded: false, - due: Date(), - completion: 0, - type: .video, - displayName: "", - studentUrl: "", - webUrl: "", - encodedVideo: .init( - fallback: nil, - youtube: nil, - desktopMP4: .init(url: "test.mp4", fileSize: 1000, streamPriority: 1, type: .desktopMP4), - mobileHigh: nil, - mobileLow: nil, - hls: nil - ), - multiDevice: true, - offlineDownload: nil - ) - - let vertical = CourseVertical( - blockId: blockId, - id: "vertical1", - courseId: "123", - displayName: "", - type: .vertical, - completion: 0, - childs: [block], - webUrl: "" - ) - - let sequential = CourseSequential( - blockId: blockId, - id: blockId, - displayName: "", - type: .chapter, - completion: 0, - childs: [vertical], - sequentialProgress: nil, - due: Date() - ) - - let chapter = CourseChapter( - blockId: blockId, - id: "1", - displayName: "Chapter 1", - type: .chapter, - childs: [sequential] - ) - - let courseStructure = CourseStructure( - id: "course123", - graded: true, - completion: 0, - viewYouTubeUrl: "", - encodedVideo: "", - displayName: "", - topicID: nil, - childs: [chapter], - media: CourseMedia( - image: CourseImage( - raw: "", - small: "", - large: "" - ) - ), - certificate: nil, - org: "", - isSelfPaced: true, - courseProgress: nil - ) - - let downloadData = DownloadDataTask( - id: "1", - blockId: "1", - courseId: "course123", - userId: 1, - url: "https://example.com/file.mp4", - fileName: "file.mp4", - displayName: "file.mp4", - progress: 0, - resumeData: nil, - state: .inProgress, - type: .video, - fileSize: 1000, - lastModified: "", - actualSize: 333 - ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) - Given(connectivity, .isMobileData(getter: false)) - - Given(downloadManager, .eventPublisher(willReturn: Just(.added).eraseToAnyPublisher())) - Given(downloadManager, .isLargeVideosSize(blocks: .any, willReturn: false)) - Given(downloadManager, .getCurrentDownloadTask(willReturn: downloadData)) - - let viewModel = CourseContainerViewModel( - interactor: interactor, - authInteractor: authInteractor, - router: router, - analytics: analytics, - config: config, - connectivity: connectivity, - manager: downloadManager, - storage: CourseStorageMock(), - isActive: true, - courseStart: Date(), - courseEnd: nil, - enrollmentStart: nil, - enrollmentEnd: nil, - lastVisitedBlockID: nil, - coreAnalytics: CoreAnalyticsMock(), - courseHelper: courseHelperMock - ) - viewModel.courseStructure = courseStructure - await viewModel.onDownloadViewTap( - chapter: chapter, - state: .available - ) - - await Task.yield() - - Verify( - analytics, - 1, - .bulkDownloadVideosSection( - courseID: .value(courseStructure.id), - sectionID: .value(chapter.id), - videos: .value(1) - ) - ) - Verify(analytics, 0, .bulkDeleteVideosSection(courseID: .any, sectionId: .any, videos: .any)) - Verify(downloadManager, 1, .addToDownloadQueue(blocks: .value([block]))) - } - - func testOnDownloadViewDownloadingTap() async { + func testTabSelectedAnalytics() { let interactor = CourseInteractorProtocolMock() let authInteractor = AuthInteractorProtocolMock() let router = CourseRouterMock() let analytics = CourseAnalyticsMock() let config = ConfigMock() let connectivity = ConnectivityProtocolMock() - let downloadManager = DownloadManagerProtocolMock() - - let blockId = "chapter:block:1" - - let block = CourseBlock( - blockId: blockId, - id: "1", - courseId: "123", - topicId: "", - graded: false, - due: Date(), - completion: 0, - type: .video, - displayName: "", - studentUrl: "", - webUrl: "", - encodedVideo: .init( - fallback: nil, - youtube: nil, - desktopMP4: .init(url: "test.mp4", fileSize: 1000, streamPriority: 1, type: .desktopMP4), - mobileHigh: nil, - mobileLow: nil, - hls: nil - ), - multiDevice: true, - offlineDownload: nil - ) - - let vertical = CourseVertical( - blockId: blockId, - id: "vertical1", - courseId: "123", - displayName: "", - type: .vertical, - completion: 0, - childs: [block], - webUrl: "" - ) - - let sequential = CourseSequential( - blockId: blockId, - id: blockId, - displayName: "", - type: .chapter, - completion: 0, - childs: [vertical], - sequentialProgress: nil, - due: Date() - ) - - let chapter = CourseChapter( - blockId: blockId, - id: "1", - displayName: "Chapter 1", - type: .chapter, - childs: [sequential] - ) - - let courseStructure = CourseStructure( - id: "123", - graded: true, - completion: 0, - viewYouTubeUrl: "", - encodedVideo: "", - displayName: "", - topicID: nil, - childs: [chapter], - media: CourseMedia( - image: CourseImage( - raw: "", - small: "", - large: "" - ) - ), - certificate: nil, - org: "", - isSelfPaced: true, - courseProgress: nil - ) - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) - Given(connectivity, .isMobileData(getter: false)) + connectivity.isInternetAvaliable = true + connectivity.internetReachableSubject = .init(.reachable) - Given(downloadManager, .eventPublisher(willReturn: Just(.added).eraseToAnyPublisher())) + let downloadManager = DownloadManagerMock() let viewModel = CourseContainerViewModel( interactor: interactor, @@ -883,717 +606,14 @@ final class CourseContainerViewModelTests: XCTestCase { coreAnalytics: CoreAnalyticsMock(), courseHelper: courseHelperMock ) - viewModel.courseStructure = courseStructure - - await viewModel.onDownloadViewTap( - chapter: chapter, - state: .downloading - ) - - await Task.yield() - Verify( - analytics, - 0, - .bulkDownloadVideosSection( - courseID: .any, - sectionID: .any, - videos: .any - ) - ) - Verify(analytics, 0, .bulkDeleteVideosSection(courseID: .any, sectionId: .any, videos: .any)) - Verify(downloadManager, 1, .cancelDownloading(courseId: .value(courseStructure.id), blocks: .value([block]))) - } - - func testOnDownloadViewFinishedTap() async throws { - let interactor = CourseInteractorProtocolMock() - let authInteractor = AuthInteractorProtocolMock() - let router = CourseRouterMock() - let analytics = CourseAnalyticsMock() - let config = ConfigMock() - let connectivity = ConnectivityProtocolMock() - let downloadManager = DownloadManagerProtocolMock() - - let blockId = "chapter:block:1" + viewModel.trackSelectedTab(selection: .course, courseId: "1", courseName: "name") + XCTAssertEqual(analytics.courseOutlineCourseTabClickedCallCount, 1) - let block = CourseBlock( - blockId: blockId, - id: "1", - courseId: "123", - topicId: "", - graded: false, - due: Date(), - completion: 0, - type: .video, - displayName: "", - studentUrl: "", - webUrl: "", - encodedVideo: .init( - fallback: nil, - youtube: nil, - desktopMP4: .init(url: "test.mp4", fileSize: 1000, streamPriority: 1, type: .desktopMP4), - mobileHigh: nil, - mobileLow: nil, - hls: nil - ), - multiDevice: true, - offlineDownload: nil - ) + viewModel.trackSelectedTab(selection: .discussion, courseId: "1", courseName: "name") + XCTAssertEqual(analytics.courseOutlineDiscussionTabClickedCallCount, 1) - let vertical = CourseVertical( - blockId: blockId, - id: "vertical1", - courseId: "123", - displayName: "", - type: .vertical, - completion: 0, - childs: [block], - webUrl: "" - ) - - let sequential = CourseSequential( - blockId: blockId, - id: blockId, - displayName: "", - type: .chapter, - completion: 0, - childs: [vertical], - sequentialProgress: nil, - due: Date() - ) - - let chapter = CourseChapter( - blockId: blockId, - id: "1", - displayName: "Chapter 1", - type: .chapter, - childs: [sequential] - ) - - let courseStructure = CourseStructure( - id: "123", - graded: true, - completion: 0, - viewYouTubeUrl: "", - encodedVideo: "", - displayName: "", - topicID: nil, - childs: [chapter], - media: CourseMedia( - image: CourseImage( - raw: "", - small: "", - large: "" - ) - ), - certificate: nil, - org: "", - isSelfPaced: true, - courseProgress: nil - ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) - Given(connectivity, .isMobileData(getter: false)) - - Given(downloadManager, .eventPublisher(willReturn: Just(.added).eraseToAnyPublisher())) - Given(courseHelperMock, .sizeFor(sequentials: .any, willReturn: 1000)) - - let viewModel = CourseContainerViewModel( - interactor: interactor, - authInteractor: authInteractor, - router: router, - analytics: analytics, - config: config, - connectivity: connectivity, - manager: downloadManager, - storage: CourseStorageMock(), - isActive: true, - courseStart: Date(), - courseEnd: nil, - enrollmentStart: nil, - enrollmentEnd: nil, - lastVisitedBlockID: nil, - coreAnalytics: CoreAnalyticsMock(), - courseHelper: courseHelperMock - ) - viewModel.courseStructure = courseStructure - - await viewModel.onDownloadViewTap( - chapter: chapter, - state: .finished - ) - - await Task.yield() - - Verify( - analytics, - 0, - .bulkDownloadVideosSection( - courseID: .any, - sectionID: .any, - videos: .any - ) - ) - Verify( - analytics, - 1, - .bulkDeleteVideosSection( - courseID: .value(courseStructure.id), - sectionId: .value(chapter.id), - videos: .value(1) - ) - ) - } - - func testSetDownloadsStatesAvailable() async throws { - let interactor = CourseInteractorProtocolMock() - let authInteractor = AuthInteractorProtocolMock() - let router = CourseRouterMock() - let analytics = CourseAnalyticsMock() - let config = ConfigMock() - let connectivity = ConnectivityProtocolMock() - let downloadManager = DownloadManagerProtocolMock() - - let blockId = "chapter:block:1" - - let block = CourseBlock( - blockId: blockId, - id: "1", - courseId: "123", - topicId: "", - graded: false, - due: Date(), - completion: 0, - type: .video, - displayName: "", - studentUrl: "", - webUrl: "", - encodedVideo: .init( - fallback: nil, - youtube: nil, - desktopMP4: .init(url: "test.mp4", fileSize: 1000, streamPriority: 1, type:.desktopMP4), - mobileHigh: nil, - mobileLow: nil, - hls: nil - ), - multiDevice: true, - offlineDownload: nil - ) - - let vertical = CourseVertical( - blockId: blockId, - id: "vertical1", - courseId: "123", - displayName: "", - type: .vertical, - completion: 0, - childs: [block], - webUrl: "" - ) - - let sequential = CourseSequential( - blockId: blockId, - id: blockId, - displayName: "", - type: .chapter, - completion: 0, - childs: [vertical], - sequentialProgress: nil, - due: Date() - ) - - let chapter = CourseChapter( - blockId: blockId, - id: "1", - displayName: "Chapter 1", - type: .chapter, - childs: [sequential] - ) - - let courseStructure = CourseStructure( - id: "123", - graded: true, - completion: 0, - viewYouTubeUrl: "", - encodedVideo: "", - displayName: "", - topicID: nil, - childs: [chapter], - media: CourseMedia( - image: CourseImage( - raw: "", - small: "", - large: "" - ) - ), - certificate: nil, - org: "", - isSelfPaced: true, - courseProgress: nil - ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) - Given(connectivity, .isMobileData(getter: false)) - - Given(downloadManager, .eventPublisher(willReturn: Just(.added).eraseToAnyPublisher())) - Given(downloadManager, .getDownloadTasks(willReturn: [])) - let courseHelper = CourseDownloadHelper(courseStructure: courseStructure, manager: downloadManager) - - let viewModel = CourseContainerViewModel( - interactor: interactor, - authInteractor: authInteractor, - router: router, - analytics: analytics, - config: config, - connectivity: connectivity, - manager: downloadManager, - storage: CourseStorageMock(), - isActive: true, - courseStart: Date(), - courseEnd: nil, - enrollmentStart: nil, - enrollmentEnd: nil, - lastVisitedBlockID: nil, - coreAnalytics: CoreAnalyticsMock(), - courseHelper: courseHelper - ) - viewModel.courseStructure = courseStructure - viewModel.courseStructure = courseStructure - viewModel.courseHelper.courseStructure = courseStructure - await viewModel.courseHelper.refreshValue() - - await Task.yield() - - XCTAssertEqual(viewModel.sequentialsDownloadState[sequential.id], .available) - } - - func testSetDownloadsStatesDownloading() async throws { - let interactor = CourseInteractorProtocolMock() - let authInteractor = AuthInteractorProtocolMock() - let router = CourseRouterMock() - let analytics = CourseAnalyticsMock() - let config = ConfigMock() - let connectivity = ConnectivityProtocolMock() - let downloadManager = DownloadManagerProtocolMock() - - let blockId = "chapter:block:1" - - let block = CourseBlock( - blockId: blockId, - id: "1", - courseId: "123", - topicId: "", - graded: false, - due: Date(), - completion: 0, - type: .video, - displayName: "", - studentUrl: "", - webUrl: "", - encodedVideo: .init( - fallback: nil, - youtube: nil, - desktopMP4: .init(url: "test.mp4", fileSize: 1000, streamPriority: 1, type:.desktopMP4), - mobileHigh: nil, - mobileLow: nil, - hls: nil - ), - multiDevice: true, - offlineDownload: nil - ) - - let vertical = CourseVertical( - blockId: blockId, - id: "vertical1", - courseId: "123", - displayName: "", - type: .vertical, - completion: 0, - childs: [block], - webUrl: "" - ) - - let sequential = CourseSequential( - blockId: blockId, - id: blockId, - displayName: "", - type: .chapter, - completion: 0, - childs: [vertical], - sequentialProgress: nil, - due: Date() - ) - - let chapter = CourseChapter( - blockId: blockId, - id: "1", - displayName: "Chapter 1", - type: .chapter, - childs: [sequential] - ) - - let courseStructure = CourseStructure( - id: "123", - graded: true, - completion: 0, - viewYouTubeUrl: "", - encodedVideo: "", - displayName: "", - topicID: nil, - childs: [chapter], - media: CourseMedia(image: CourseImage(raw: "", - small: "", - large: "")), - certificate: nil, - org: "", - isSelfPaced: true, - courseProgress: nil - ) - - let downloadData = DownloadDataTask( - id: "1", - blockId: "1", - courseId: "123", - userId: 1, - url: "https://example.com/file.mp4", - fileName: "file.mp4", - displayName: "file.mp4", - progress: 0, - resumeData: nil, - state: .inProgress, - type: .video, - fileSize: 1000, - lastModified: "", - actualSize: 333 - ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) - Given(connectivity, .isMobileData(getter: false)) - - Given(downloadManager, .eventPublisher(willReturn: Just(.added).eraseToAnyPublisher())) - Given(downloadManager, .getDownloadTasks(willReturn: [downloadData])) - let courseHelper = CourseDownloadHelper(courseStructure: courseStructure, manager: downloadManager) - let viewModel = CourseContainerViewModel( - interactor: interactor, - authInteractor: authInteractor, - router: router, - analytics: analytics, - config: config, - connectivity: connectivity, - manager: downloadManager, - storage: CourseStorageMock(), - isActive: true, - courseStart: Date(), - courseEnd: nil, - enrollmentStart: nil, - enrollmentEnd: nil, - lastVisitedBlockID: nil, - coreAnalytics: CoreAnalyticsMock(), - courseHelper: courseHelper - ) - viewModel.courseStructure = courseStructure - viewModel.courseHelper.courseStructure = courseStructure - await viewModel.courseHelper.refreshValue() - - await Task.yield() - - XCTAssertEqual(viewModel.sequentialsDownloadState[sequential.id], .downloading) - } - - func testSetDownloadsStatesFinished() async throws { - let interactor = CourseInteractorProtocolMock() - let authInteractor = AuthInteractorProtocolMock() - let router = CourseRouterMock() - let analytics = CourseAnalyticsMock() - let config = ConfigMock() - let connectivity = ConnectivityProtocolMock() - let downloadManager = DownloadManagerProtocolMock() - - let blockId = "chapter:block:1" - - let block = CourseBlock( - blockId: blockId, - id: "1", - courseId: "123", - topicId: "", - graded: false, - due: Date(), - completion: 0, - type: .video, - displayName: "", - studentUrl: "", - webUrl: "", - encodedVideo: .init( - fallback: nil, - youtube: nil, - desktopMP4: .init(url: "test.mp4", fileSize: 1000, streamPriority: 1, type:.desktopMP4), - mobileHigh: nil, - mobileLow: nil, - hls: nil - ), - multiDevice: true, - offlineDownload: nil - ) - - let vertical = CourseVertical( - blockId: blockId, - id: "vertical1", - courseId: "123", - displayName: "", - type: .vertical, - completion: 0, - childs: [block], - webUrl: "" - ) - - let sequential = CourseSequential( - blockId: blockId, - id: blockId, - displayName: "", - type: .chapter, - completion: 0, - childs: [vertical], - sequentialProgress: nil, - due: Date() - ) - - let chapter = CourseChapter( - blockId: blockId, - id: "1", - displayName: "Chapter 1", - type: .chapter, - childs: [sequential] - ) - - let courseStructure = CourseStructure( - id: "123", - graded: true, - completion: 0, - viewYouTubeUrl: "", - encodedVideo: "", - displayName: "", - topicID: nil, - childs: [chapter], - media: CourseMedia(image: CourseImage(raw: "", - small: "", - large: "")), - certificate: nil, - org: "", - isSelfPaced: true, - courseProgress: nil - ) - - let downloadData = DownloadDataTask( - id: "1", - blockId: "1", - courseId: "123", - userId: 1, - url: "https://example.com/file.mp4", - fileName: "file.mp4", - displayName: "file.mp4", - progress: 0, - resumeData: nil, - state: .finished, - type: .video, - fileSize: 1000, - lastModified: "", - actualSize: 333 - ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) - Given(connectivity, .isMobileData(getter: false)) - - Given(downloadManager, .eventPublisher(willReturn: Just(.added).eraseToAnyPublisher())) - Given(downloadManager, .getDownloadTasks(willReturn: [downloadData])) - let courseHelper = CourseDownloadHelper(courseStructure: courseStructure, manager: downloadManager) - let viewModel = CourseContainerViewModel( - interactor: interactor, - authInteractor: authInteractor, - router: router, - analytics: analytics, - config: config, - connectivity: connectivity, - manager: downloadManager, - storage: CourseStorageMock(), - isActive: true, - courseStart: Date(), - courseEnd: nil, - enrollmentStart: nil, - enrollmentEnd: nil, - lastVisitedBlockID: nil, - coreAnalytics: CoreAnalyticsMock(), - courseHelper: courseHelper - ) - viewModel.courseStructure = courseStructure - viewModel.courseHelper.courseStructure = courseStructure - await viewModel.courseHelper.refreshValue() - - await Task.yield() - - XCTAssertEqual(viewModel.sequentialsDownloadState[sequential.id], .finished) - } - - func testSetDownloadsStatesPartiallyFinished() async throws { - let interactor = CourseInteractorProtocolMock() - let authInteractor = AuthInteractorProtocolMock() - let router = CourseRouterMock() - let analytics = CourseAnalyticsMock() - let config = ConfigMock() - let connectivity = ConnectivityProtocolMock() - let downloadManager = DownloadManagerProtocolMock() - - let blockId = "chapter:block:1" - - let block = CourseBlock( - blockId: blockId, - id: "1", - courseId: "123", - topicId: "", - graded: false, - due: Date(), - completion: 0, - type: .video, - displayName: "", - studentUrl: "", - webUrl: "", - encodedVideo: .init( - fallback: nil, - youtube: nil, - desktopMP4: .init(url: "test.mp4", fileSize: 1000, streamPriority: 1, type:.desktopMP4), - mobileHigh: nil, - mobileLow: nil, - hls: nil - ), - multiDevice: true, - offlineDownload: nil - ) - let block2 = CourseBlock( - blockId: "123", - id: "1213", - courseId: "123", - topicId: "", - graded: false, - due: Date(), - completion: 0, - type: .video, - displayName: "", - studentUrl: "", - webUrl: "", - encodedVideo: .init( - fallback: nil, - youtube: nil, - desktopMP4: .init(url: "test.mp4", fileSize: 1000, streamPriority: 1, type:.desktopMP4), - mobileHigh: nil, - mobileLow: nil, - hls: nil - ), - multiDevice: true, - offlineDownload: nil - ) - - let vertical = CourseVertical( - blockId: blockId, - id: "vertical1", - courseId: "123", - displayName: "", - type: .vertical, - completion: 0, - childs: [block, block2], - webUrl: "" - ) - - let sequential = CourseSequential( - blockId: blockId, - id: blockId, - displayName: "", - type: .chapter, - completion: 0, - childs: [vertical], - sequentialProgress: nil, - due: Date() - ) - - let chapter = CourseChapter( - blockId: blockId, - id: "1", - displayName: "Chapter 1", - type: .chapter, - childs: [sequential] - ) - - let courseStructure = CourseStructure( - id: "123", - graded: true, - completion: 0, - viewYouTubeUrl: "", - encodedVideo: "", - displayName: "", - topicID: nil, - childs: [chapter], - media: CourseMedia( - image: CourseImage( - raw: "", - small: "", - large: "" - ) - ), - certificate: nil, - org: "", - isSelfPaced: true, - courseProgress: nil - ) - - let downloadData = DownloadDataTask( - id: "1", - blockId: "1", - courseId: "123", - userId: 1, - url: "https://example.com/file.mp4", - fileName: "file.mp4", - displayName: "file.mp4", - progress: 0, - resumeData: nil, - state: .finished, - type: .video, - fileSize: 1000, - lastModified: "", - actualSize: 333 - ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) - Given(connectivity, .isMobileData(getter: false)) - - Given(downloadManager, .eventPublisher(willReturn: Just(.added).eraseToAnyPublisher())) - Given(downloadManager, .getDownloadTasks(willReturn: [downloadData])) - let courseHelper = CourseDownloadHelper(courseStructure: courseStructure, manager: downloadManager) - let viewModel = CourseContainerViewModel( - interactor: interactor, - authInteractor: authInteractor, - router: router, - analytics: analytics, - config: config, - connectivity: connectivity, - manager: downloadManager, - storage: CourseStorageMock(), - isActive: true, - courseStart: Date(), - courseEnd: nil, - enrollmentStart: nil, - enrollmentEnd: nil, - lastVisitedBlockID: nil, - coreAnalytics: CoreAnalyticsMock(), - courseHelper: courseHelper - ) - viewModel.courseStructure = courseStructure - viewModel.courseHelper.courseStructure = courseStructure - await viewModel.courseHelper.refreshValue() - await Task.yield() - - XCTAssertEqual(viewModel.sequentialsDownloadState[sequential.id], .available) + viewModel.trackSelectedTab(selection: .handounds, courseId: "1", courseName: "name") + XCTAssertEqual(analytics.courseOutlineHandoutsTabClickedCallCount, 1) } } diff --git a/Course/CourseTests/Presentation/Container/CourseDownloadHelperTests.swift b/Course/CourseTests/Presentation/Container/CourseDownloadHelperTests.swift index 7baf92dea..7d2a04934 100644 --- a/Course/CourseTests/Presentation/Container/CourseDownloadHelperTests.swift +++ b/Course/CourseTests/Presentation/Container/CourseDownloadHelperTests.swift @@ -7,7 +7,6 @@ import Core import Combine -import SwiftyMocky import XCTest @testable import Course @@ -23,7 +22,7 @@ final class CourseDownloadHelperTests: XCTestCase { var task: DownloadDataTask! var value: CourseDownloadValue! var timeout: TimeInterval = 15 - + override func setUp() { super.setUp() downloadManagerMock = DownloadManagerProtocolMock() @@ -50,7 +49,7 @@ final class CourseDownloadHelperTests: XCTestCase { multiDevice: true, offlineDownload: nil ) - + let vertical = CourseVertical( blockId: "", id: "", @@ -78,9 +77,9 @@ final class CourseDownloadHelperTests: XCTestCase { type: .chapter, childs: [sequential] ) - + let childs = [chapter] - + let courseStructure = CourseStructure( id: "123", graded: true, @@ -115,147 +114,55 @@ final class CourseDownloadHelperTests: XCTestCase { largestBlocks: [], state: .cancel ) - Given(downloadManagerMock, .getDownloadTasks(willReturn: [task!])) - Given(downloadManagerMock, .getCurrentDownloadTask(willReturn: task)) - Given(downloadManagerMock, .eventPublisher(willReturn: downloadPublisher.eraseToAnyPublisher())) + let taskCopy = task! + let publisher = downloadPublisher.eraseToAnyPublisher() + downloadManagerMock.getDownloadTasksHandler = { [taskCopy] in [taskCopy] } + downloadManagerMock.getCurrentDownloadTaskHandler = { [taskCopy] in taskCopy } + downloadManagerMock.eventPublisherHandler = { publisher } helper = CourseDownloadHelper(courseStructure: courseStructure, manager: downloadManagerMock) } - + override func tearDown() { super.tearDown() cancellables.removeAll() cancellables = [] } - -// ToDo: re-think how to test it - https://github.com/openedx/openedx-app-ios/issues/576 -// -// func testPublisher_whenRefresh_ShouldSendValue() { -// // given -// var valueReceived: CourseDownloadValue? -// let expectation = expectation(description: "wait for publisher") -// helper.publisher() -// .sink { value in -// valueReceived = value -// expectation.fulfill() -// } -// .store(in: &cancellables) -// -// // when -// helper.refreshValue() -// -// // then -// wait(for: [expectation], timeout: timeout) -// Verify(downloadManagerMock, .once, .getDownloadTasks()) -// Verify(downloadManagerMock, .once, .getCurrentDownloadTask()) -// XCTAssertEqual(valueReceived, value) -// } - -// func testPublisher_whenAsyncRefresh_ShouldSendValue() async { -// // given -// var valueReceived: CourseDownloadValue? -// let expectation = expectation(description: "wait for publisher") -// helper.publisher() -// .sink { value in -// valueReceived = value -// expectation.fulfill() -// } -// .store(in: &cancellables) -// -// // when -// await helper.refreshValue() -// -// // then -// await fulfillment(of: [expectation], timeout: timeout) -// Verify(downloadManagerMock, .once, .getDownloadTasks()) -// Verify(downloadManagerMock, .once, .getCurrentDownloadTask()) -// XCTAssertEqual(valueReceived, value) -// } - -// func testPublisher_whenReceivedNotProgressEvent_ShouldSendValue() async { -// // given -// var valueReceived: CourseDownloadValue? -// var receivedCount = 0 -// let addedExpectation = expectation(description: "wait for added event") -// -// let expectations: [XCTestExpectation] = [ -// addedExpectation -// ] -// -// helper.publisher() -// .sink { value in -// expectations[receivedCount].fulfill() -// receivedCount += 1 -// valueReceived = value -// } -// .store(in: &cancellables) -// // when -// downloadPublisher.send(.added) //1 -// // then -// await fulfillment(of: expectations, timeout: timeout) -// Verify(downloadManagerMock, .once, .getDownloadTasks()) -// Verify(downloadManagerMock, .once, .getCurrentDownloadTask()) -// XCTAssertEqual(receivedCount, 1) -// XCTAssertEqual(valueReceived, value) -// } - -// func testEventPublisher_whenReceivedProgressEvent_ShouldSendEvent() async { -// // given -// var valueReceived: DownloadDataTask? -// task.progress = 0.5 -// let expectation = expectation(description: "wait for progress event") -// var countOfEvents: Int = 0 -// helper.progressPublisher() -// .sink { value in -// expectation.fulfill() -// countOfEvents += 1 -// valueReceived = value -// } -// .store(in: &cancellables) -// helper.value = value -// // when -// downloadPublisher.send(.progress(task)) -// // then -// await fulfillment(of: [expectation], timeout: timeout) -// value.currentDownloadTask = task -// XCTAssertEqual(helper.value, value) -// XCTAssertEqual(valueReceived, task) -// XCTAssertEqual(countOfEvents, 1) -// Verify(downloadManagerMock, .never, .getDownloadTasks()) -// Verify(downloadManagerMock, .never, .getCurrentDownloadTask()) -// } - + func testSizeForBlock_whenCalled_ShouldReturnSize() { // when let size = helper.sizeFor(block: block) // then XCTAssertEqual(size, block.fileSize) } - + func testSizeForBlocks_whenCalled_ShouldReturnSize() { // when let size = helper.sizeFor(blocks: [block]) // then XCTAssertEqual(size, block.fileSize) } - + func testSizeForSequential_whenCalled_ShouldReturnSize() { // when let size = helper.sizeFor(sequential: sequential) // then XCTAssertEqual(size, sequential.totalSize) } - + func testSizeForSequentials_whenCalled_ShouldReturnSize() { // when let size = helper.sizeFor(sequentials: [sequential]) // then XCTAssertEqual(size, sequential.totalSize) } - + func testCancelDownloading_whenCalled_ShouldCallManagerMethod() async throws { + // given + downloadManagerMock.cancelDownloadingTaskHandler = { _ in } // when try await helper.cancelDownloading(task: task) // then - Verify(downloadManagerMock, .cancelDownloading(task: .value(task))) + XCTAssertEqual(downloadManagerMock.cancelDownloadingTaskCallCount, 1) } } + diff --git a/Course/CourseTests/Presentation/Unit/CourseDateViewModelTests.swift b/Course/CourseTests/Presentation/Unit/CourseDateViewModelTests.swift index cf80332b4..cd7ad9d69 100644 --- a/Course/CourseTests/Presentation/Unit/CourseDateViewModelTests.swift +++ b/Course/CourseTests/Presentation/Unit/CourseDateViewModelTests.swift @@ -7,7 +7,6 @@ import XCTest import Alamofire -import SwiftyMocky @testable import Core @testable import Course @@ -18,8 +17,8 @@ final class CourseDateViewModelTests: XCTestCase { let router = CourseRouterMock() let cssInjector = CSSInjectorMock() let connectivity = ConnectivityProtocolMock() - let config = ConfigMock() - + let config = ConfigProtocolMock() + let courseDates = CourseDates( datesBannerInfo: DatesBannerInfo( @@ -32,7 +31,7 @@ final class CourseDateViewModelTests: XCTestCase { hasEnded: false, learnerIsFullAccess: false, userTimezone: nil) - + let courseStructure = CourseStructure( id: "123", graded: true, @@ -54,10 +53,10 @@ final class CourseDateViewModelTests: XCTestCase { isSelfPaced: true, courseProgress: nil ) - - Given(interactor, .getCourseDates(courseID: .any, willReturn: courseDates)) - Given(interactor, .getLoadedCourseBlocks(courseID: .any, willReturn: courseStructure)) - + + interactor.getCourseDatesHandler = { _ in courseDates } + interactor.getLoadedCourseBlocksHandler = { _ in courseStructure } + let viewModel = CourseDatesViewModel( interactor: interactor, router: router, @@ -66,29 +65,28 @@ final class CourseDateViewModelTests: XCTestCase { config: config, courseID: "1", courseName: "a", - analytics: CourseAnalyticsMock(), - calendarManager: CalendarManagerMock() + analytics: CourseAnalyticsMock(), + calendarManager: CalendarManagerProtocolMock() ) - + await viewModel.getCourseDates(courseID: "1") - - Verify(interactor, .getCourseDates(courseID: .any)) - - XCTAssert((viewModel.courseDates != nil)) + + XCTAssertEqual(interactor.getCourseDatesCallCount, 1) + XCTAssertNotNil(viewModel.courseDates) XCTAssertFalse(viewModel.isShowProgress) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.showError) } - + func testGetCourseDatesUnknownError() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let cssInjector = CSSInjectorMock() let connectivity = ConnectivityProtocolMock() - let config = ConfigMock() - - Given(interactor, .getCourseDates(courseID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + let config = ConfigProtocolMock() + + interactor.getCourseDatesHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + let viewModel = CourseDatesViewModel( interactor: interactor, router: router, @@ -98,28 +96,27 @@ final class CourseDateViewModelTests: XCTestCase { courseID: "1", courseName: "a", analytics: CourseAnalyticsMock(), - calendarManager: CalendarManagerMock() + calendarManager: CalendarManagerProtocolMock() ) - + await viewModel.getCourseDates(courseID: "1") - - Verify(interactor, .getCourseDates(courseID: .any)) - + + XCTAssertEqual(interactor.getCourseDatesCallCount, 1) XCTAssertNil(viewModel.courseDates) XCTAssertFalse(viewModel.isShowProgress) } - + func testNoInternetConnectionError() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let cssInjector = CSSInjectorMock() let connectivity = ConnectivityProtocolMock() - let config = ConfigMock() - + let config = ConfigProtocolMock() + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .getCourseDates(courseID: .any, willThrow: noInternetError)) - + + interactor.getCourseDatesHandler = { _ in throw noInternetError } + let viewModel = CourseDatesViewModel( interactor: interactor, router: router, @@ -129,17 +126,16 @@ final class CourseDateViewModelTests: XCTestCase { courseID: "1", courseName: "a", analytics: CourseAnalyticsMock(), - calendarManager: CalendarManagerMock() + calendarManager: CalendarManagerProtocolMock() ) - + await viewModel.getCourseDates(courseID: "1") - - Verify(interactor, .getCourseDates(courseID: .any)) - + + XCTAssertEqual(interactor.getCourseDatesCallCount, 1) XCTAssertNil(viewModel.courseDates) XCTAssertFalse(viewModel.isShowProgress) } - + func testSortedDateTodayToCourseDateBlockDict() { let block1 = CourseDateBlock( assignmentType: nil, @@ -155,7 +151,7 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockID1", useRelativeDates: true ) - + let block2 = CourseDateBlock( assignmentType: nil, complete: true, @@ -170,7 +166,7 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockID1", useRelativeDates: true ) - + let courseDates = CourseDates( datesBannerInfo: DatesBannerInfo( missedDeadlines: false, @@ -184,12 +180,12 @@ final class CourseDateViewModelTests: XCTestCase { learnerIsFullAccess: true, userTimezone: nil ) - + let sortedDict = courseDates.statusDatesBlocks[.completed] - + XCTAssertEqual(sortedDict?.keys.sorted().first, Date.today) } - + func testMultipleBlocksForSameDate() { let block1 = CourseDateBlock( assignmentType: nil, @@ -202,10 +198,10 @@ final class CourseDateViewModelTests: XCTestCase { linkText: nil, title: "TestBlock", extraInfo: nil, - firstComponentBlockID: "blockID1", + firstComponentBlockID: "blockID1", useRelativeDates: true ) - + let block2 = CourseDateBlock( assignmentType: nil, complete: true, @@ -220,7 +216,7 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockID1", useRelativeDates: true ) - + let courseDates = CourseDates( datesBannerInfo: DatesBannerInfo( missedDeadlines: false, @@ -234,11 +230,11 @@ final class CourseDateViewModelTests: XCTestCase { learnerIsFullAccess: true, userTimezone: nil ) - + let sortedDict = courseDates.statusDatesBlocks[.completed] XCTAssertEqual(sortedDict?[block1.date]?.count, 2, "There should be two blocks for the given date.") } - + func testBlockStatusForAssignmentType() { let block = CourseDateBlock( assignmentType: nil, @@ -254,10 +250,10 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockID3", useRelativeDates: true ) - + XCTAssertEqual(block.blockStatus, .dueNext) } - + func testBadgeLogicForToday() { let block = CourseDateBlock( assignmentType: nil, @@ -273,10 +269,10 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockIDTest", useRelativeDates: true ) - + XCTAssertEqual(block.title, "Today", "Block title for 'today' should be 'Today'") } - + func testBadgeLogicForCompleted() { let block = CourseDateBlock( assignmentType: nil, @@ -294,7 +290,7 @@ final class CourseDateViewModelTests: XCTestCase { ) XCTAssertEqual(block.blockStatus, .completed, "Block status for a completed assignment should be 'completed'") } - + func testBadgeLogicForVerifiedOnly() { let block = CourseDateBlock( assignmentType: nil, @@ -310,10 +306,10 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockIDTest", useRelativeDates: true ) - + XCTAssertEqual(block.blockStatus, .verifiedOnly, "Block status for a block without learner access should be 'verifiedOnly'") } - + func testBadgeLogicForPastDue() { let block = CourseDateBlock( assignmentType: nil, @@ -329,10 +325,10 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockIDTest", useRelativeDates: true ) - + XCTAssertEqual(block.blockStatus, .pastDue, "Block status for a past due assignment should be 'pastDue'") } - + func testLinkForAvailableAssignment() { let availableAssignment = CourseDateBlock( assignmentType: nil, @@ -350,7 +346,7 @@ final class CourseDateViewModelTests: XCTestCase { ) XCTAssertTrue(availableAssignment.canShowLink, "Available assignments should be hyperlinked.") } - + func testIsAssignment() { let block = CourseDateBlock( assignmentType: nil, @@ -366,10 +362,10 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockIDTest", useRelativeDates: true ) - + XCTAssertTrue(block.isAssignment) } - + func testIsCourseStartDate() { let block = CourseDateBlock( assignmentType: nil, @@ -385,10 +381,10 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockIDTest", useRelativeDates: true ) - + XCTAssertEqual(block.blockStatus, BlockStatus.courseStartDate) } - + func testIsCourseEndDate() { let block = CourseDateBlock( assignmentType: nil, @@ -404,10 +400,10 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockIDTest", useRelativeDates: true ) - + XCTAssertEqual(block.blockStatus, BlockStatus.courseEndDate) } - + func testVerifiedOnly() { let block = CourseDateBlock( assignmentType: nil, @@ -423,10 +419,10 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockIDTest", useRelativeDates: true ) - + XCTAssertTrue(block.isVerifiedOnly, "Block should be identified as 'verified only' when the learner has no access.") } - + func testIsCompleted() { let block = CourseDateBlock( assignmentType: nil, @@ -442,10 +438,10 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockIDTest", useRelativeDates: true ) - + XCTAssertTrue(block.isComplete, "Block should be marked as completed.") } - + func testBadgeLogicForUnreleasedAssignment() { let block = CourseDateBlock( assignmentType: nil, @@ -461,10 +457,10 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockIDTest", useRelativeDates: true ) - + XCTAssertEqual(block.blockStatus, .unreleased, "Block status should be set to 'unreleased' for unreleased assignments.") } - + func testNoLinkForUnavailableAssignment() { let block = CourseDateBlock( assignmentType: nil, @@ -480,11 +476,11 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockIDTest", useRelativeDates: true ) - + XCTAssertEqual(block.blockStatus, .verifiedOnly) XCTAssertFalse(block.canShowLink, "Block should not show a link if the assignment is unavailable.") } - + func testNoLinkAvailableForUnreleasedAssignment() { let block = CourseDateBlock( assignmentType: nil, @@ -500,30 +496,30 @@ final class CourseDateViewModelTests: XCTestCase { firstComponentBlockID: "blockIDTest", useRelativeDates: true ) - + XCTAssertEqual(block.blockStatus, .unreleased) XCTAssertFalse(block.canShowLink, "Block should not show a link if the assignment is unreleased.") } - + func testTodayProperty() { let today = Date.today let currentDay = Calendar.current.startOfDay(for: Date()) XCTAssertTrue(today.isToday, "The today property should return true for isToday.") XCTAssertEqual(today, currentDay, "The today property should equal the start of the current day.") } - + func testDateIsInPastProperty() { let pastDate = Date().addingTimeInterval(-100000) XCTAssertTrue(pastDate.isInPast, "The past date should return true for isInPast.") XCTAssertFalse(pastDate.isToday, "The past date should return false for isInPast.") } - + func testDateIsInFutureProperty() { let futureDate = Date().addingTimeInterval(100000) XCTAssertTrue(futureDate.isInFuture, "The future date should return false for isInFuture.") XCTAssertFalse(futureDate.isToday, "The future date should return false for isInFuture.") } - + func testBlockStatusMapping() { XCTAssertEqual(BlockStatus.status(of: "course-start-date"), .courseStartDate, "Incorrect mapping for 'course-start-date'") XCTAssertEqual(BlockStatus.status(of: "course-end-date"), .courseEndDate, "Incorrect mapping for 'course-end-date'") diff --git a/Course/CourseTests/Presentation/Unit/CourseProgressViewModelTests.swift b/Course/CourseTests/Presentation/Unit/CourseProgressViewModelTests.swift index 26c8320bd..4266c541b 100644 --- a/Course/CourseTests/Presentation/Unit/CourseProgressViewModelTests.swift +++ b/Course/CourseTests/Presentation/Unit/CourseProgressViewModelTests.swift @@ -5,7 +5,6 @@ // Created by Ivan Stepanok on 20.06.2025. // -import SwiftyMocky import XCTest @testable import Core @testable import Course @@ -14,7 +13,7 @@ import SwiftUI @MainActor final class CourseProgressViewModelTests: XCTestCase { - + static let mockCourseProgress = CourseProgressDetails( verifiedMode: nil, accessExpiration: nil, @@ -84,7 +83,7 @@ final class CourseProgressViewModelTests: XCTestCase { ], verificationData: nil ) - + static let mockEmptyProgress = CourseProgressDetails( verifiedMode: nil, accessExpiration: nil, @@ -122,21 +121,20 @@ final class CourseProgressViewModelTests: XCTestCase { let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getCourseProgress(courseID: .any, willReturn: CourseProgressViewModelTests.mockCourseProgress)) - + + connectivity.isInternetAvaliable = true + interactor.getCourseProgressHandler = { _ in CourseProgressViewModelTests.mockCourseProgress } + await viewModel.getCourseProgress(courseID: "test-course-id") - - Verify(interactor, .getCourseProgress(courseID: .any)) - + + XCTAssertEqual(interactor.getCourseProgressCallCount, 1) XCTAssertFalse(viewModel.isLoading) XCTAssertFalse(viewModel.showError) XCTAssertNotNil(viewModel.courseProgress) @@ -148,141 +146,136 @@ final class CourseProgressViewModelTests: XCTestCase { let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - - Given(connectivity, .isInternetAvaliable(getter: false)) - Given(interactor, .getCourseProgressOffline(courseID: .any, willReturn: CourseProgressViewModelTests.mockCourseProgress)) - + + connectivity.isInternetAvaliable = false + interactor.getCourseProgressOfflineHandler = { _ in CourseProgressViewModelTests.mockCourseProgress } + await viewModel.getCourseProgress(courseID: "test-course-id") - - Verify(interactor, .getCourseProgressOffline(courseID: .any)) - + + XCTAssertEqual(interactor.getCourseProgressOfflineCallCount, 1) XCTAssertFalse(viewModel.isLoading) XCTAssertFalse(viewModel.showError) XCTAssertNotNil(viewModel.courseProgress) } - + func testGetCourseProgressUnknownError() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getCourseProgress(courseID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + + connectivity.isInternetAvaliable = true + interactor.getCourseProgressHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + await viewModel.getCourseProgress(courseID: "test-course-id") - - Verify(interactor, .getCourseProgress(courseID: .any)) - + + XCTAssertEqual(interactor.getCourseProgressCallCount, 1) XCTAssertFalse(viewModel.isLoading) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) } - + func testGetCourseProgressNoInternetError() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getCourseProgress(courseID: .any, willThrow: noInternetError)) - + + connectivity.isInternetAvaliable = true + interactor.getCourseProgressHandler = { _ in throw noInternetError } + await viewModel.getCourseProgress(courseID: "test-course-id") - - Verify(interactor, .getCourseProgress(courseID: .any)) - + + XCTAssertEqual(interactor.getCourseProgressCallCount, 1) XCTAssertFalse(viewModel.isLoading) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) } - + func testGetCourseProgressNoCacheError() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getCourseProgress(courseID: .any, willThrow: NoCachedDataError())) - + + connectivity.isInternetAvaliable = true + interactor.getCourseProgressHandler = { _ in throw NoCachedDataError() } + await viewModel.getCourseProgress(courseID: "test-course-id") - - Verify(interactor, .getCourseProgress(courseID: .any)) - + + XCTAssertEqual(interactor.getCourseProgressCallCount, 1) XCTAssertFalse(viewModel.isLoading) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) } - + func testTrackProgressTabClicked() { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + viewModel.trackProgressTabClicked(courseId: "test-course", courseName: "Test Course") - - Verify(analytics, .courseOutlineProgressTabClicked(courseId: .any, courseName: .any)) + + XCTAssertEqual(analytics.courseOutlineProgressTabClickedCallCount, 1) } - + func testRefreshProgress() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getCourseProgress(courseID: .any, willReturn: CourseProgressViewModelTests.mockCourseProgress)) - + + connectivity.isInternetAvaliable = true + interactor.getCourseProgressHandler = { _ in CourseProgressViewModelTests.mockCourseProgress } + await viewModel.getCourseProgress(courseID: "test-course-id", withProgress: false) - - Verify(interactor, .getCourseProgress(courseID: .any)) - + + XCTAssertEqual(interactor.getCourseProgressCallCount, 1) XCTAssertFalse(viewModel.isLoading) XCTAssertNotNil(viewModel.courseProgress) } @@ -292,151 +285,151 @@ final class CourseProgressViewModelTests: XCTestCase { let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + // Test with nil progress XCTAssertTrue(viewModel.isProgressEmpty) - + // Test with empty progress viewModel.courseProgress = CourseProgressViewModelTests.mockEmptyProgress XCTAssertTrue(viewModel.isProgressEmpty) - + // Test with non-empty progress viewModel.courseProgress = CourseProgressViewModelTests.mockCourseProgress XCTAssertFalse(viewModel.isProgressEmpty) } - + func testHasGradedAssignments() { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + // Test with nil progress XCTAssertFalse(viewModel.hasGradedAssignments) - + // Test with empty progress viewModel.courseProgress = CourseProgressViewModelTests.mockEmptyProgress XCTAssertFalse(viewModel.hasGradedAssignments) - + // Test with progress that has graded assignments viewModel.courseProgress = CourseProgressViewModelTests.mockCourseProgress XCTAssertTrue(viewModel.hasGradedAssignments) } - + func testOverallProgressPercentage() { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + // Test with nil progress XCTAssertEqual(viewModel.overallProgressPercentage, 0.0) - + // Test with actual progress viewModel.courseProgress = CourseProgressViewModelTests.mockCourseProgress XCTAssertEqual(viewModel.overallProgressPercentage, 0.8) // 8/10 = 0.8 } - + func testGradePercentage() { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + // Test with nil progress XCTAssertEqual(viewModel.gradePercentage, 0.0) - + // Test with actual progress viewModel.courseProgress = CourseProgressViewModelTests.mockCourseProgress XCTAssertEqual(viewModel.gradePercentage, 0.85) } - + func testIsPassing() { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + // Test with nil progress XCTAssertFalse(viewModel.isPassing) - + // Test with passing progress viewModel.courseProgress = CourseProgressViewModelTests.mockCourseProgress XCTAssertTrue(viewModel.isPassing) } - + func testHasCertificate() { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + // Test with nil progress XCTAssertFalse(viewModel.hasCertificate) - + // Test with certificate available viewModel.courseProgress = CourseProgressViewModelTests.mockCourseProgress XCTAssertTrue(viewModel.hasCertificate) } - + func testCertificateUrl() { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + // Test with nil progress XCTAssertNil(viewModel.certificateUrl) - + // Test with certificate URL viewModel.courseProgress = CourseProgressViewModelTests.mockCourseProgress XCTAssertEqual(viewModel.certificateUrl, "https://example.com/download") @@ -447,65 +440,65 @@ final class CourseProgressViewModelTests: XCTestCase { let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + // Test with nil progress XCTAssertEqual(viewModel.requiredGradePercentage, 0.0) - + // Test with actual progress viewModel.courseProgress = CourseProgressViewModelTests.mockCourseProgress XCTAssertEqual(viewModel.requiredGradePercentage, 0.6) } - + func testAssignmentPolicies() { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + // Test with nil progress XCTAssertTrue(viewModel.assignmentPolicies.isEmpty) - + // Test with actual progress viewModel.courseProgress = CourseProgressViewModelTests.mockCourseProgress XCTAssertEqual(viewModel.assignmentPolicies.count, 2) XCTAssertEqual(viewModel.assignmentPolicies[0].type, "Homework") XCTAssertEqual(viewModel.assignmentPolicies[1].type, "Exam") } - + func testGetAssignmentProgress() { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + // Test with nil progress let emptyProgress = viewModel.getAssignmentProgress(for: "Homework", courseStructure: nil) XCTAssertEqual(emptyProgress.completed, 0) XCTAssertEqual(emptyProgress.total, 0) XCTAssertEqual(emptyProgress.earnedPoints, 0.0) XCTAssertEqual(emptyProgress.possiblePoints, 0.0) - + // Test with actual progress viewModel.courseProgress = CourseProgressViewModelTests.mockCourseProgress let homeworkProgress = viewModel.getAssignmentProgress(for: "Homework", courseStructure: self.createMockCourseStructure()) @@ -515,24 +508,24 @@ final class CourseProgressViewModelTests: XCTestCase { XCTAssertEqual(homeworkProgress.possiblePoints, 10.0) XCTAssertEqual(homeworkProgress.percentGraded, 0.8) } - + func testGetAllAssignmentProgressData() { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseProgressViewModel( interactor: interactor, router: router, analytics: analytics, connectivity: connectivity ) - + // Test with nil progress let emptyData = viewModel.getAllAssignmentProgressData() XCTAssertTrue(emptyData.isEmpty) - + // Test with actual progress viewModel.courseStructure = createMockCourseStructure() viewModel.courseProgress = CourseProgressViewModelTests.mockCourseProgress diff --git a/Course/CourseTests/Presentation/Unit/CourseUnitViewModelTests.swift b/Course/CourseTests/Presentation/Unit/CourseUnitViewModelTests.swift index 2c89fdb81..803b3e27b 100644 --- a/Course/CourseTests/Presentation/Unit/CourseUnitViewModelTests.swift +++ b/Course/CourseTests/Presentation/Unit/CourseUnitViewModelTests.swift @@ -2,10 +2,9 @@ // CourseUnitViewModelTests.swift // CourseTests // -// Created by  Stepanok Ivan on 23.01.2023. +// Created by Stepanok Ivan on 23.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Course @@ -14,14 +13,14 @@ import SwiftUI @MainActor final class CourseUnitViewModelTests: XCTestCase { - var config = Config() + var config = ConfigMock() static let blocks = [ CourseBlock(blockId: "1", id: "1", courseId: "123", topicId: "1", - graded: false, + graded: false, due: Date(), completion: 0, type: .video, @@ -78,7 +77,7 @@ final class CourseUnitViewModelTests: XCTestCase { offlineDownload: nil ), ] - + let chapters = [ CourseChapter( blockId: "0", @@ -107,7 +106,7 @@ final class CourseUnitViewModelTests: XCTestCase { sequentialProgress: nil, due: Date() ) - + ]), CourseChapter( blockId: "2", @@ -136,16 +135,16 @@ final class CourseUnitViewModelTests: XCTestCase { sequentialProgress: nil, due: Date() ) - + ]) ] - + func testBlockCompletionRequestSuccess() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseUnitViewModel( lessonID: "123", courseID: "456", @@ -162,20 +161,20 @@ final class CourseUnitViewModelTests: XCTestCase { storage: CourseStorageMock(), manager: DownloadManagerMock() ) - - Given(interactor, .blockCompletionRequest(courseID: .any, blockID: .any, willProduce: {_ in})) - + + interactor.blockCompletionRequestHandler = { _, _ in } + await viewModel.blockCompletionRequest(blockID: "1") - - Verify(interactor, .blockCompletionRequest(courseID: .any, blockID: .any)) + + XCTAssertEqual(interactor.blockCompletionRequestCallCount, 1) } - + func testBlockCompletionRequestUnknownError() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseUnitViewModel( lessonID: "123", courseID: "456", @@ -188,29 +187,28 @@ final class CourseUnitViewModelTests: XCTestCase { config: config, router: router, analytics: analytics, - connectivity: connectivity, + connectivity: connectivity, storage: CourseStorageMock(), manager: DownloadManagerMock() ) - - Given(interactor, .blockCompletionRequest(courseID: .any, - blockID: .any, - willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + + interactor.blockCompletionRequestHandler = { _, _ in + throw NSError(domain: "error", code: -1, userInfo: nil) + } + await viewModel.blockCompletionRequest(blockID: "1") - - Verify(interactor, .blockCompletionRequest(courseID: .any, blockID: .any)) - + + XCTAssertEqual(interactor.blockCompletionRequestCallCount, 1) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) } - + func testBlockCompletionRequestNoInternetError() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseUnitViewModel( lessonID: "123", courseID: "456", @@ -227,27 +225,26 @@ final class CourseUnitViewModelTests: XCTestCase { storage: CourseStorageMock(), manager: DownloadManagerMock() ) - + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - Given(interactor, .blockCompletionRequest(courseID: .any, - blockID: .any, - willThrow: noInternetError)) - + interactor.blockCompletionRequestHandler = { _, _ in + throw noInternetError + } + await viewModel.blockCompletionRequest(blockID: "1") - - Verify(interactor, .blockCompletionRequest(courseID: .any, blockID: .any)) - + + XCTAssertEqual(interactor.blockCompletionRequestCallCount, 1) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) } - + func testBlockCompletionRequestNoCacheError() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseUnitViewModel( lessonID: "123", courseID: "456", @@ -264,26 +261,25 @@ final class CourseUnitViewModelTests: XCTestCase { storage: CourseStorageMock(), manager: DownloadManagerMock() ) - - Given(interactor, .blockCompletionRequest(courseID: .any, - blockID: .any, - willThrow: NoCachedDataError())) - + + interactor.blockCompletionRequestHandler = { _, _ in + throw NoCachedDataError() + } + await viewModel.blockCompletionRequest(blockID: "1") - - Verify(interactor, .blockCompletionRequest(courseID: .any, blockID: .any)) - + + XCTAssertEqual(interactor.blockCompletionRequestCallCount, 1) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) } - - + + func testCourseNavigation() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() let analytics = CourseAnalyticsMock() - + let viewModel = CourseUnitViewModel( lessonID: "123", courseID: "456", @@ -300,23 +296,21 @@ final class CourseUnitViewModelTests: XCTestCase { storage: CourseStorageMock(), manager: DownloadManagerMock() ) - + viewModel.loadIndex() - + for _ in 0...CourseUnitViewModelTests.blocks.count - 1 { viewModel.select(move: .next) } - - Verify(analytics, .nextBlockClicked(courseId: .any, courseName: .any, blockId: .any, blockName: .any)) - + + XCTAssertTrue(analytics.nextBlockClickedCallCount > 0) XCTAssertEqual(viewModel.index, 3) - + for _ in 0...CourseUnitViewModelTests.blocks.count - 1 { viewModel.select(move: .previous) } - - Verify(analytics, .prevBlockClicked(courseId: .any, courseName: .any, blockId: .any, blockName: .any)) - + + XCTAssertTrue(analytics.prevBlockClickedCallCount > 0) XCTAssertEqual(viewModel.index, 0) } } diff --git a/Course/CourseTests/Presentation/Unit/HandoutsViewModelTests.swift b/Course/CourseTests/Presentation/Unit/HandoutsViewModelTests.swift index 0db68e007..962bd0911 100644 --- a/Course/CourseTests/Presentation/Unit/HandoutsViewModelTests.swift +++ b/Course/CourseTests/Presentation/Unit/HandoutsViewModelTests.swift @@ -2,10 +2,9 @@ // HandoutsViewModelTests.swift // CourseTests // -// Created by  Stepanok Ivan on 28.02.2023. +// Created by Stepanok Ivan on 28.02.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Course @@ -14,17 +13,17 @@ import SwiftUI @MainActor final class HandoutsViewModelTests: XCTestCase { - + func testGetHandoutsSuccess() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() - + let courseUpdate = [CourseUpdate(id: 1, date: "1", content: "Update", status: "1")] - - Given(interactor, .getHandouts(courseID: .any, willReturn: "Result")) - Given(interactor, .getUpdates(courseID: .any, willReturn: courseUpdate)) - + + interactor.getHandoutsHandler = { _ in "Result" } + interactor.getUpdatesHandler = { _ in courseUpdate } + let viewModel = HandoutsViewModel( interactor: interactor, router: router, @@ -32,27 +31,26 @@ final class HandoutsViewModelTests: XCTestCase { connectivity: connectivity, courseID: "123", analytics: CourseAnalyticsMock()) - + await viewModel.getHandouts(courseID: "") - - Verify(interactor, 1, .getHandouts(courseID: .any)) - - XCTAssert(viewModel.handouts == "Result") + + XCTAssertEqual(interactor.getHandoutsCallCount, 1) + XCTAssertEqual(viewModel.handouts, "Result") XCTAssertFalse(viewModel.isShowProgress) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.showError) } - + func testGetHandoutsNoInternetError() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() - + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .getHandouts(courseID: .any, willThrow: noInternetError)) - Given(interactor, .getUpdates(courseID: .any, willThrow: noInternetError)) - + + interactor.getHandoutsHandler = { _ in throw noInternetError } + interactor.getUpdatesHandler = { _ in throw noInternetError } + let viewModel = HandoutsViewModel( interactor: interactor, router: router, @@ -60,23 +58,22 @@ final class HandoutsViewModelTests: XCTestCase { connectivity: connectivity, courseID: "123", analytics: CourseAnalyticsMock()) - + await viewModel.getHandouts(courseID: "") - - Verify(interactor, 1, .getHandouts(courseID: .any)) - - XCTAssert(viewModel.handouts == nil) + + XCTAssertEqual(interactor.getHandoutsCallCount, 1) + XCTAssertNil(viewModel.handouts) XCTAssertFalse(viewModel.isShowProgress) } - + func testGetHandoutsUnknownError() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() - - Given(interactor, .getHandouts(courseID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - Given(interactor, .getUpdates(courseID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + + interactor.getHandoutsHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + interactor.getUpdatesHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + let viewModel = HandoutsViewModel( interactor: interactor, router: router, @@ -84,24 +81,23 @@ final class HandoutsViewModelTests: XCTestCase { connectivity: connectivity, courseID: "123", analytics: CourseAnalyticsMock()) - + await viewModel.getHandouts(courseID: "") - - Verify(interactor, 1, .getHandouts(courseID: .any)) - - XCTAssert(viewModel.handouts == nil) + + XCTAssertEqual(interactor.getHandoutsCallCount, 1) + XCTAssertNil(viewModel.handouts) XCTAssertFalse(viewModel.isShowProgress) } - + func testGetUpdatesSuccess() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() - + let courseUpdate = [CourseUpdate(id: 1, date: "1", content: "Update", status: "1")] - - Given(interactor, .getUpdates(courseID: .any, willReturn: courseUpdate)) - + + interactor.getUpdatesHandler = { _ in courseUpdate } + let viewModel = HandoutsViewModel( interactor: interactor, router: router, @@ -109,22 +105,21 @@ final class HandoutsViewModelTests: XCTestCase { connectivity: connectivity, courseID: "123", analytics: CourseAnalyticsMock()) - + await viewModel.getUpdates(courseID: "") - - Verify(interactor, 1, .getUpdates(courseID: .any)) - - XCTAssert(viewModel.updates[0].content == "Update") + + XCTAssertEqual(interactor.getUpdatesCallCount, 1) + XCTAssertEqual(viewModel.updates[0].content, "Update") XCTAssertFalse(viewModel.isShowProgress) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.showError) } - + func testGetUpdatesNoInternetError() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() - + let viewModel = HandoutsViewModel( interactor: interactor, router: router, @@ -132,24 +127,23 @@ final class HandoutsViewModelTests: XCTestCase { connectivity: connectivity, courseID: "123", analytics: CourseAnalyticsMock()) - + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .getUpdates(courseID: .any, willThrow: noInternetError)) - + + interactor.getUpdatesHandler = { _ in throw noInternetError } + await viewModel.getUpdates(courseID: "") - - Verify(interactor, 1, .getUpdates(courseID: .any)) - + + XCTAssertEqual(interactor.getUpdatesCallCount, 1) XCTAssertTrue(viewModel.updates.isEmpty) XCTAssertFalse(viewModel.isShowProgress) } - + func testGetUpdatesUnknownError() async throws { let interactor = CourseInteractorProtocolMock() let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() - + let viewModel = HandoutsViewModel( interactor: interactor, router: router, @@ -157,16 +151,13 @@ final class HandoutsViewModelTests: XCTestCase { connectivity: connectivity, courseID: "123", analytics: CourseAnalyticsMock()) - - - Given(interactor, .getUpdates(courseID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + + interactor.getUpdatesHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + await viewModel.getUpdates(courseID: "") - - Verify(interactor, 1, .getUpdates(courseID: .any)) - + + XCTAssertEqual(interactor.getUpdatesCallCount, 1) XCTAssertTrue(viewModel.updates.isEmpty) XCTAssertFalse(viewModel.isShowProgress) } - } diff --git a/Course/CourseTests/Presentation/Unit/VideoPlayerViewModelTests.swift b/Course/CourseTests/Presentation/Unit/VideoPlayerViewModelTests.swift index a5af0d0b8..7c8c4b040 100644 --- a/Course/CourseTests/Presentation/Unit/VideoPlayerViewModelTests.swift +++ b/Course/CourseTests/Presentation/Unit/VideoPlayerViewModelTests.swift @@ -2,200 +2,178 @@ // VideoPlayerViewModelTests.swift // CourseTests // -// Created by  Stepanok Ivan on 12.04.2023. +// Created by Stepanok Ivan on 12.04.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Course -import Alamofire -import SwiftUI +import Combine @MainActor final class VideoPlayerViewModelTests: XCTestCase { - - let subtitles = [ - Subtitle(id: 0, - fromTo: DateInterval(start: Date(), end: Date()) , - text: "GREGORY NAGY: In hour zero, where I try to introduce Homeric poetry to"), - Subtitle(id: 1, - fromTo: DateInterval(start: Date(), end: Date()) , - text: "people who may never have been exposed to the Iliad and the Odyssey even in"), - Subtitle(id: 2, - fromTo: DateInterval(start: Date(), end: Date()) , - text: "translation, my idea was to get a sense of the medium, which is not a"), - ] + + private func makePlayerHolder(service: PlayerServiceProtocolMock) -> PlayerViewControllerHolderProtocolMock { + let playerHolder = PlayerViewControllerHolderProtocolMock() + playerHolder.getServiceHandler = { service } + playerHolder.getTimePublisherHandler = { Empty().eraseToAnyPublisher() } + playerHolder.getErrorPublisherHandler = { Empty().eraseToAnyPublisher() } + playerHolder.getRatePublisherHandler = { Empty().eraseToAnyPublisher() } + playerHolder.getReadyPublisherHandler = { Empty().eraseToAnyPublisher() } + playerHolder.getFinishPublisherHandler = { Empty().eraseToAnyPublisher() } + return playerHolder + } func testGetSubtitlesSuccess() async throws { - let interactor = CourseInteractorProtocolMock() - let router = CourseRouterMock() let connectivity = ConnectivityProtocolMock() - - Given(interactor, .getSubtitles(url: .any, selectedLanguage: .any, willReturn: subtitles)) - - let tracker = PlayerTrackerProtocolMock(url: nil) - let service = PlayerService(courseID: "", blockID: "", interactor: interactor, router: router) - let playerHolder = PlayerViewControllerHolder(url: nil, blockID: "", courseID: "", selectedCourseTab: 0, pipManager: PipManagerProtocolMock(), playerTracker: tracker, playerDelegate: nil, playerService: service, appStorage: CoreStorageMock()) + let analytics = CourseAnalyticsMock() + let appStorage = CoreStorageMock() + + connectivity.isInternetAvaliable = true + connectivity.internetReachableSubject = CurrentValueSubject(.reachable) + + let subtitles = [ + Subtitle( + id: 1, + fromTo: DateInterval(start: Date(), duration: 5), + text: "Hello World" + ) + ] + + let playerService = PlayerServiceProtocolMock() + playerService.getSubtitlesHandler = { _, _ in subtitles } + + let playerHolder = makePlayerHolder(service: playerService) + let viewModel = VideoPlayerViewModel( languages: [], connectivity: connectivity, playerHolder: playerHolder, - appStorage: CoreStorageMock(), - analytics: CourseAnalyticsMock() + appStorage: appStorage, + analytics: analytics ) - - await viewModel.getSubtitles(subtitlesUrl: "url") - - Verify(interactor, .getSubtitles(url: .any, selectedLanguage: .any)) - - XCTAssertEqual(viewModel.subtitles.first!.text, subtitles.first!.text) - XCTAssertNil(viewModel.errorMessage) - XCTAssertFalse(viewModel.showError) + + await viewModel.getSubtitles(subtitlesUrl: "https://example.com/subs.vtt") + + XCTAssertEqual(playerService.getSubtitlesCallCount, 1) + XCTAssertFalse(viewModel.subtitles.isEmpty) + XCTAssertEqual(viewModel.subtitles.first?.text, "Hello World") } - - func testGetSubtitlesOfflineSuccess() async throws { - let interactor = CourseInteractorProtocolMock() - let router = CourseRouterMock() + + func testGetSubtitlesError() async throws { let connectivity = ConnectivityProtocolMock() - - - - Given(connectivity, .isInternetAvaliable(getter: false)) - Given(interactor, .getSubtitles(url: .any, selectedLanguage: .any, willReturn: subtitles)) - - let tracker = PlayerTrackerProtocolMock(url: nil) - let service = PlayerService(courseID: "", blockID: "", interactor: interactor, router: router) - let playerHolder = PlayerViewControllerHolder(url: nil, blockID: "", courseID: "", selectedCourseTab: 0, pipManager: PipManagerProtocolMock(), playerTracker: tracker, playerDelegate: nil, playerService: service, appStorage: CoreStorageMock()) + let analytics = CourseAnalyticsMock() + let appStorage = CoreStorageMock() + + connectivity.isInternetAvaliable = true + connectivity.internetReachableSubject = CurrentValueSubject(.reachable) + + let playerService = PlayerServiceProtocolMock() + playerService.getSubtitlesHandler = { _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + + let playerHolder = makePlayerHolder(service: playerService) + let viewModel = VideoPlayerViewModel( languages: [], connectivity: connectivity, playerHolder: playerHolder, - appStorage: CoreStorageMock(), - analytics: CourseAnalyticsMock() + appStorage: appStorage, + analytics: analytics ) - - await viewModel.getSubtitles(subtitlesUrl: "url") - - Verify(interactor, .getSubtitles(url: .any, selectedLanguage: .any)) - - XCTAssertEqual(viewModel.subtitles.first!.text, subtitles.first!.text) - XCTAssertNil(viewModel.errorMessage) - XCTAssertFalse(viewModel.showError) + + await viewModel.getSubtitles(subtitlesUrl: "https://example.com/subs.vtt") + + XCTAssertEqual(playerService.getSubtitlesCallCount, 1) + XCTAssertTrue(viewModel.subtitles.isEmpty) } - - func testGenerates() async { - let interactor = CourseInteractorProtocolMock() - let router = CourseRouterMock() + + func testGenerateLanguageName() async throws { let connectivity = ConnectivityProtocolMock() - - let tracker = PlayerTrackerProtocolMock(url: nil) - let service = PlayerService(courseID: "", blockID: "", interactor: interactor, router: router) - let playerHolder = PlayerViewControllerHolder(url: nil, blockID: "", courseID: "", selectedCourseTab: 0, pipManager: PipManagerProtocolMock(), playerTracker: tracker, playerDelegate: nil, playerService: service, appStorage: CoreStorageMock()) + let analytics = CourseAnalyticsMock() + let appStorage = CoreStorageMock() + + connectivity.isInternetAvaliable = true + connectivity.internetReachableSubject = CurrentValueSubject(.reachable) + + let playerService = PlayerServiceProtocolMock() + let playerHolder = makePlayerHolder(service: playerService) + let viewModel = VideoPlayerViewModel( languages: [], connectivity: connectivity, playerHolder: playerHolder, - appStorage: CoreStorageMock(), - analytics: CourseAnalyticsMock() + appStorage: appStorage, + analytics: analytics ) - viewModel.languages = [ - SubtitleUrl(language: "en", url: "url"), - SubtitleUrl(language: "uk", url: "url2") - ] - - Given(interactor, .getSubtitles(url: .any, selectedLanguage: .any, willReturn: subtitles)) - - await viewModel.getSubtitles(subtitlesUrl: "url") - viewModel.prepareLanguages() - - let language = viewModel.generateLanguageName(code: "en") - - XCTAssertEqual(language, "English") - } - - func testBlockCompletionRequest() async throws { - let interactor = CourseInteractorProtocolMock() - let router = CourseRouterMock() - - let tracker = PlayerTrackerProtocolMock(url: nil) - let service = PlayerService(courseID: "", blockID: "", interactor: interactor, router: router) - let playerHolder = PlayerViewControllerHolder( - url: nil, - blockID: "", - courseID: "", - selectedCourseTab: 0, - pipManager: PipManagerProtocolMock(), - playerTracker: tracker, - playerDelegate: nil, - playerService: service, - appStorage: CoreStorageMock() - ) - - Given(interactor, .blockCompletionRequest(courseID: .any, blockID: .any, willProduce: {_ in})) - - await playerHolder.sendCompletion() - - await Task.yield() - - Verify(interactor, .blockCompletionRequest(courseID: .any, blockID: .any)) + let englishName = viewModel.generateLanguageName(code: "en") + XCTAssertEqual(englishName, "English") + + let ukrainianName = viewModel.generateLanguageName(code: "uk") + XCTAssertEqual(ukrainianName, "Українська") } - - func testBlockCompletionRequestUnknownError() async throws { - let interactor = CourseInteractorProtocolMock() - let router = CourseRouterMock() + + func testGeneratePickerItems() async throws { let connectivity = ConnectivityProtocolMock() - - let tracker = PlayerTrackerProtocolMock(url: nil) - let service = PlayerService(courseID: "", blockID: "", interactor: interactor, router: router) - let playerHolder = PlayerViewControllerHolder(url: nil, blockID: "", courseID: "", selectedCourseTab: 0, pipManager: PipManagerProtocolMock(), playerTracker: tracker, playerDelegate: nil, playerService: service, appStorage: CoreStorageMock()) + let analytics = CourseAnalyticsMock() + let appStorage = CoreStorageMock() + + connectivity.isInternetAvaliable = true + connectivity.internetReachableSubject = CurrentValueSubject(.reachable) + + let languages = [ + SubtitleUrl(language: "en", url: "https://example.com/subs_en.vtt"), + SubtitleUrl(language: "uk", url: "https://example.com/subs_uk.vtt") + ] + + let playerService = PlayerServiceProtocolMock() + playerService.getSubtitlesHandler = { _, _ in [] } + let playerHolder = makePlayerHolder(service: playerService) + let viewModel = VideoPlayerViewModel( - languages: [], + languages: languages, connectivity: connectivity, playerHolder: playerHolder, - appStorage: CoreStorageMock(), - analytics: CourseAnalyticsMock() + appStorage: appStorage, + analytics: analytics ) - - Given(interactor, .blockCompletionRequest(courseID: .any, blockID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - - await playerHolder.sendCompletion() - - Verify(interactor, .blockCompletionRequest(courseID: .any, blockID: .any)) - await Task.yield() - - XCTAssertTrue(viewModel.showError) - XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) + + // Items should include 2 languages + XCTAssertEqual(viewModel.items.count, 2) } - - func testBlockCompletionRequestNoInternetError() async throws { - let interactor = CourseInteractorProtocolMock() - let router = CourseRouterMock() + + func testFindSubtitle() async throws { let connectivity = ConnectivityProtocolMock() - - let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - let tracker = PlayerTrackerProtocolMock(url: nil) - let service = PlayerService(courseID: "", blockID: "", interactor: interactor, router: router) - let playerHolder = PlayerViewControllerHolder(url: nil, blockID: "", courseID: "", selectedCourseTab: 0, pipManager: PipManagerProtocolMock(), playerTracker: tracker, playerDelegate: nil, playerService: service, appStorage: CoreStorageMock()) + let analytics = CourseAnalyticsMock() + let appStorage = CoreStorageMock() + + connectivity.isInternetAvaliable = true + connectivity.internetReachableSubject = CurrentValueSubject(.reachable) + + let playerService = PlayerServiceProtocolMock() + let playerHolder = makePlayerHolder(service: playerService) + let viewModel = VideoPlayerViewModel( languages: [], connectivity: connectivity, playerHolder: playerHolder, - appStorage: CoreStorageMock(), - analytics: CourseAnalyticsMock() + appStorage: appStorage, + analytics: analytics + ) + + let now = Date() + let subtitle = Subtitle( + id: 1, + fromTo: DateInterval(start: now, duration: 5), + text: "Hello World" ) - - Given(interactor, .blockCompletionRequest(courseID: .any, blockID: .any, willThrow: noInternetError)) - - await playerHolder.sendCompletion() - - await Task.yield() - - Verify(interactor, .blockCompletionRequest(courseID: .any, blockID: .any)) - - XCTAssertTrue(viewModel.showError) - XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) + viewModel.subtitles = [subtitle] + + let foundSubtitle = viewModel.findSubtitle(at: now.addingTimeInterval(2)) + XCTAssertNotNil(foundSubtitle) + XCTAssertEqual(foundSubtitle?.text, "Hello World") + + let notFoundSubtitle = viewModel.findSubtitle(at: now.addingTimeInterval(10)) + XCTAssertNil(notFoundSubtitle) } } diff --git a/Course/Mockfile b/Course/Mockfile deleted file mode 100644 index 42d9b4b0e..000000000 --- a/Course/Mockfile +++ /dev/null @@ -1,18 +0,0 @@ -sourceryCommand: mint run krzysztofzablocki/Sourcery@2.1.2 sourcery -sourceryTemplate: ../MockTemplate.swifttemplate -unit.tests.mock: - sources: - include: - - ./../Core - - ./Course - exclude: [] - output: ./CourseTests/CourseMock.generated.swift - targets: - - MyAppUnitTests - import: - - Core - - Course - - Foundation - - SwiftUI - - Combine - - OEXFoundation \ No newline at end of file diff --git a/Dashboard/Dashboard.xcodeproj/project.pbxproj b/Dashboard/Dashboard.xcodeproj/project.pbxproj index 48dda4c64..3bebbb2c3 100644 --- a/Dashboard/Dashboard.xcodeproj/project.pbxproj +++ b/Dashboard/Dashboard.xcodeproj/project.pbxproj @@ -27,7 +27,6 @@ 02A98F172BD97886009B46BD /* CategoryFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A98F162BD97885009B46BD /* CategoryFilterView.swift */; }; 02A9A90B2978194100B55797 /* DashboardViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A9A90A2978194100B55797 /* DashboardViewModelTests.swift */; }; 02A9A90C2978194100B55797 /* Dashboard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02EF39E728D89F560058F6BD /* Dashboard.framework */; platformFilter = ios; }; - 02A9A92929781A4D00B55797 /* DashboardMock.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A9A92829781A4D00B55797 /* DashboardMock.generated.swift */; }; 02F175332A4DABBF0019CD70 /* DashboardAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F175322A4DABBF0019CD70 /* DashboardAnalytics.swift */; }; 02F3BFE129252FCB0051930C /* DashboardRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F3BFE029252FCB0051930C /* DashboardRouter.swift */; }; 02F6EF3D28D9EB8C00835477 /* swiftgen.yml in Resources */ = {isa = PBXBuildFile; fileRef = 02F6EF3C28D9EB8C00835477 /* swiftgen.yml */; }; @@ -36,6 +35,7 @@ 214DA1AADABC7BF4FB8EA1D7 /* Pods_App_Dashboard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B008B2F0762EF35CADE3DD4 /* Pods_App_Dashboard.framework */; }; 97E7DF0B2B7A3EAF00A2A09B /* CourseEnrollmentsMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97E7DF0A2B7A3EAF00A2A09B /* CourseEnrollmentsMock.swift */; }; 9AD4A6A1AAF97092CF457FE2 /* Pods_App_Dashboard_DashboardTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22905947A936093AD23D4CF8 /* Pods_App_Dashboard_DashboardTests.framework */; }; + A5B4681A2F29E583002A4ECA /* DashboardMocks.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B468182F29E583002A4ECA /* DashboardMocks.generated.swift */; }; CE1735062CD2552A00F9606A /* PrimaryCourseDashboardViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1735052CD2552A00F9606A /* PrimaryCourseDashboardViewModelTests.swift */; }; CE17350A2CD26CB500F9606A /* AllCoursesViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1735092CD26CB500F9606A /* AllCoursesViewModelTests.swift */; }; CEB1E26D2CC14E9B00921517 /* OEXFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CEB1E26C2CC14E9B00921517 /* OEXFoundation */; }; @@ -72,7 +72,6 @@ 02A98F162BD97885009B46BD /* CategoryFilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryFilterView.swift; sourceTree = ""; }; 02A9A9082978194100B55797 /* DashboardTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DashboardTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 02A9A90A2978194100B55797 /* DashboardViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardViewModelTests.swift; sourceTree = ""; }; - 02A9A92829781A4D00B55797 /* DashboardMock.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashboardMock.generated.swift; sourceTree = ""; }; 02EF39E728D89F560058F6BD /* Dashboard.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Dashboard.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 02F175322A4DABBF0019CD70 /* DashboardAnalytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardAnalytics.swift; sourceTree = ""; }; 02F3BFE029252FCB0051930C /* DashboardRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardRouter.swift; sourceTree = ""; }; @@ -92,6 +91,7 @@ 6BA3D1943CAB859ECDC95C76 /* Pods-App-Dashboard.releasedev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Dashboard.releasedev.xcconfig"; path = "Target Support Files/Pods-App-Dashboard/Pods-App-Dashboard.releasedev.xcconfig"; sourceTree = ""; }; 89D6F05AC9854DBBAB091D9C /* Pods-App-Dashboard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Dashboard.release.xcconfig"; path = "Target Support Files/Pods-App-Dashboard/Pods-App-Dashboard.release.xcconfig"; sourceTree = ""; }; 97E7DF0A2B7A3EAF00A2A09B /* CourseEnrollmentsMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseEnrollmentsMock.swift; sourceTree = ""; }; + A5B468182F29E583002A4ECA /* DashboardMocks.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardMocks.generated.swift; sourceTree = ""; }; BBABB135366FFB1DAEFA0D16 /* Pods-App-Dashboard-DashboardTests.debugprod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Dashboard-DashboardTests.debugprod.xcconfig"; path = "Target Support Files/Pods-App-Dashboard-DashboardTests/Pods-App-Dashboard-DashboardTests.debugprod.xcconfig"; sourceTree = ""; }; CCF4C665AD91B6B96F6A11DF /* Pods-App-Dashboard-DashboardTests.debugdev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Dashboard-DashboardTests.debugdev.xcconfig"; path = "Target Support Files/Pods-App-Dashboard-DashboardTests/Pods-App-Dashboard-DashboardTests.debugdev.xcconfig"; sourceTree = ""; }; CE1735052CD2552A00F9606A /* PrimaryCourseDashboardViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrimaryCourseDashboardViewModelTests.swift; sourceTree = ""; }; @@ -177,8 +177,8 @@ 02A9A9092978194100B55797 /* DashboardTests */ = { isa = PBXGroup; children = ( + A5B468192F29E583002A4ECA /* Generated */, 0766DFD2299AD99B00EBEF6A /* Presentation */, - 02A9A92829781A4D00B55797 /* DashboardMock.generated.swift */, ); path = DashboardTests; sourceTree = ""; @@ -292,6 +292,14 @@ path = Mock; sourceTree = ""; }; + A5B468192F29E583002A4ECA /* Generated */ = { + isa = PBXGroup; + children = ( + A5B468182F29E583002A4ECA /* DashboardMocks.generated.swift */, + ); + path = Generated; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -313,7 +321,6 @@ 02A9A9042978194100B55797 /* Sources */, 02A9A9052978194100B55797 /* Frameworks */, 02A9A9062978194100B55797 /* Resources */, - B524A3C31A8C77CB36DC820C /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -469,23 +476,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - B524A3C31A8C77CB36DC820C /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Dashboard-DashboardTests/Pods-App-Dashboard-DashboardTests-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Dashboard-DashboardTests/Pods-App-Dashboard-DashboardTests-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App-Dashboard-DashboardTests/Pods-App-Dashboard-DashboardTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -495,7 +485,7 @@ files = ( 02A9A90B2978194100B55797 /* DashboardViewModelTests.swift in Sources */, CE17350A2CD26CB500F9606A /* AllCoursesViewModelTests.swift in Sources */, - 02A9A92929781A4D00B55797 /* DashboardMock.generated.swift in Sources */, + A5B4681A2F29E583002A4ECA /* DashboardMocks.generated.swift in Sources */, CE1735062CD2552A00F9606A /* PrimaryCourseDashboardViewModelTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Dashboard/Dashboard/Domain/DashboardInteractor.swift b/Dashboard/Dashboard/Domain/DashboardInteractor.swift index ec859296c..91bad00e9 100644 --- a/Dashboard/Dashboard/Domain/DashboardInteractor.swift +++ b/Dashboard/Dashboard/Domain/DashboardInteractor.swift @@ -8,7 +8,7 @@ import Foundation import Core -//sourcery: AutoMockable +/// @mockable public protocol DashboardInteractorProtocol: Sendable { func getEnrollments(page: Int) async throws -> [CourseItem] func getEnrollmentsOffline() async throws -> [CourseItem] diff --git a/Dashboard/Dashboard/Presentation/AllCoursesView.swift b/Dashboard/Dashboard/Presentation/AllCoursesView.swift index 8b8e77acc..cfcb97753 100644 --- a/Dashboard/Dashboard/Presentation/AllCoursesView.swift +++ b/Dashboard/Dashboard/Presentation/AllCoursesView.swift @@ -206,7 +206,7 @@ struct AllCoursesView_Previews: PreviewProvider { let vm = AllCoursesViewModel( interactor: DashboardInteractor.mock, connectivity: Connectivity(config: ConfigMock()), - analytics: DashboardAnalyticsMock(), + analytics: DashboardAnalyticsPreviewMock(), storage: CoreStorageMock() ) diff --git a/Dashboard/Dashboard/Presentation/DashboardAnalytics.swift b/Dashboard/Dashboard/Presentation/DashboardAnalytics.swift index 2dab5cf39..c8a73315a 100644 --- a/Dashboard/Dashboard/Presentation/DashboardAnalytics.swift +++ b/Dashboard/Dashboard/Presentation/DashboardAnalytics.swift @@ -7,7 +7,7 @@ import Foundation -//sourcery: AutoMockable +/// @mockable public protocol DashboardAnalytics { func dashboardCourseClicked(courseID: String, courseName: String) func mainProgramsClicked() @@ -15,7 +15,7 @@ public protocol DashboardAnalytics { } #if DEBUG -class DashboardAnalyticsMock: DashboardAnalytics { +class DashboardAnalyticsPreviewMock: DashboardAnalytics { public func dashboardCourseClicked(courseID: String, courseName: String) {} public func mainProgramsClicked() {} public func mainCoursesClicked() {} diff --git a/Dashboard/Dashboard/Presentation/ListDashboardView.swift b/Dashboard/Dashboard/Presentation/ListDashboardView.swift index ac397f6d6..fe745ae40 100644 --- a/Dashboard/Dashboard/Presentation/ListDashboardView.swift +++ b/Dashboard/Dashboard/Presentation/ListDashboardView.swift @@ -164,7 +164,7 @@ struct ListDashboardView_Previews: PreviewProvider { let vm = ListDashboardViewModel( interactor: DashboardInteractor.mock, connectivity: Connectivity(config: ConfigMock()), - analytics: DashboardAnalyticsMock(), + analytics: DashboardAnalyticsPreviewMock(), storage: CoreStorageMock() ) let router = DashboardRouterMock() diff --git a/Dashboard/Dashboard/Presentation/PrimaryCourseDashboardView.swift b/Dashboard/Dashboard/Presentation/PrimaryCourseDashboardView.swift index 7bec9698c..170dea778 100644 --- a/Dashboard/Dashboard/Presentation/PrimaryCourseDashboardView.swift +++ b/Dashboard/Dashboard/Presentation/PrimaryCourseDashboardView.swift @@ -334,7 +334,7 @@ struct PrimaryCourseDashboardView_Previews: PreviewProvider { let vm = PrimaryCourseDashboardViewModel( interactor: DashboardInteractor.mock, connectivity: Connectivity(config: ConfigMock()), - analytics: DashboardAnalyticsMock(), + analytics: DashboardAnalyticsPreviewMock(), config: ConfigMock(), storage: CoreStorageMock(), router: DashboardRouterMock() diff --git a/Dashboard/DashboardTests/DashboardMock.generated.swift b/Dashboard/DashboardTests/DashboardMock.generated.swift deleted file mode 100644 index 80add5014..000000000 --- a/Dashboard/DashboardTests/DashboardMock.generated.swift +++ /dev/null @@ -1,5132 +0,0 @@ -// Generated using Sourcery 2.1.2 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT - - -// Generated with SwiftyMocky 4.2.0 -// Required Sourcery: 1.8.0 - - -import SwiftyMocky -import XCTest -import Core -import Dashboard -import Foundation -import SwiftUI -import Combine -import OEXFoundation - - -// MARK: - AuthInteractorProtocol - -open class AuthInteractorProtocolMock: AuthInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - @discardableResult - open func login(username: String, password: String) throws -> User { - addInvocation(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) - let perform = methodPerformValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) as? (String, String) -> Void - perform?(`username`, `password`) - var __value: User - do { - __value = try methodReturnValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(username: String, password: String). Use given") - Failure("Stub return value not specified for login(username: String, password: String). Use given") - } catch { - throw error - } - return __value - } - - @discardableResult - open func login(externalToken: String, backend: String) throws -> User { - addInvocation(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) - let perform = methodPerformValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) as? (String, String) -> Void - perform?(`externalToken`, `backend`) - var __value: User - do { - __value = try methodReturnValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - Failure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - } catch { - throw error - } - return __value - } - - open func login(ssoToken: String) throws -> User { - addInvocation(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) - let perform = methodPerformValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) as? (String) -> Void - perform?(`ssoToken`) - var __value: User - do { - __value = try methodReturnValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(ssoToken: String). Use given") - Failure("Stub return value not specified for login(ssoToken: String). Use given") - } catch { - throw error - } - return __value - } - - open func resetPassword(email: String) throws -> ResetPassword { - addInvocation(.m_resetPassword__email_email(Parameter.value(`email`))) - let perform = methodPerformValue(.m_resetPassword__email_email(Parameter.value(`email`))) as? (String) -> Void - perform?(`email`) - var __value: ResetPassword - do { - __value = try methodReturnValue(.m_resetPassword__email_email(Parameter.value(`email`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for resetPassword(email: String). Use given") - Failure("Stub return value not specified for resetPassword(email: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCookies(force: Bool) throws { - addInvocation(.m_getCookies__force_force(Parameter.value(`force`))) - let perform = methodPerformValue(.m_getCookies__force_force(Parameter.value(`force`))) as? (Bool) -> Void - perform?(`force`) - do { - _ = try methodReturnValue(.m_getCookies__force_force(Parameter.value(`force`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getRegistrationFields() throws -> [PickerFields] { - addInvocation(.m_getRegistrationFields) - let perform = methodPerformValue(.m_getRegistrationFields) as? () -> Void - perform?() - var __value: [PickerFields] - do { - __value = try methodReturnValue(.m_getRegistrationFields).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getRegistrationFields(). Use given") - Failure("Stub return value not specified for getRegistrationFields(). Use given") - } catch { - throw error - } - return __value - } - - open func registerUser(fields: [String: String], isSocial: Bool) throws -> User { - addInvocation(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) - let perform = methodPerformValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) as? ([String: String], Bool) -> Void - perform?(`fields`, `isSocial`) - var __value: User - do { - __value = try methodReturnValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - Failure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - } catch { - throw error - } - return __value - } - - open func validateRegistrationFields(fields: [String: String]) throws -> [String: String] { - addInvocation(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) - let perform = methodPerformValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) as? ([String: String]) -> Void - perform?(`fields`) - var __value: [String: String] - do { - __value = try methodReturnValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - Failure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_login__username_usernamepassword_password(Parameter, Parameter) - case m_login__externalToken_externalTokenbackend_backend(Parameter, Parameter) - case m_login__ssoToken_ssoToken(Parameter) - case m_resetPassword__email_email(Parameter) - case m_getCookies__force_force(Parameter) - case m_getRegistrationFields - case m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>, Parameter) - case m_validateRegistrationFields__fields_fields(Parameter<[String: String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_login__username_usernamepassword_password(let lhsUsername, let lhsPassword), .m_login__username_usernamepassword_password(let rhsUsername, let rhsPassword)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsername, rhs: rhsUsername, with: matcher), lhsUsername, rhsUsername, "username")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPassword, rhs: rhsPassword, with: matcher), lhsPassword, rhsPassword, "password")) - return Matcher.ComparisonResult(results) - - case (.m_login__externalToken_externalTokenbackend_backend(let lhsExternaltoken, let lhsBackend), .m_login__externalToken_externalTokenbackend_backend(let rhsExternaltoken, let rhsBackend)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsExternaltoken, rhs: rhsExternaltoken, with: matcher), lhsExternaltoken, rhsExternaltoken, "externalToken")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBackend, rhs: rhsBackend, with: matcher), lhsBackend, rhsBackend, "backend")) - return Matcher.ComparisonResult(results) - - case (.m_login__ssoToken_ssoToken(let lhsSsotoken), .m_login__ssoToken_ssoToken(let rhsSsotoken)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSsotoken, rhs: rhsSsotoken, with: matcher), lhsSsotoken, rhsSsotoken, "ssoToken")) - return Matcher.ComparisonResult(results) - - case (.m_resetPassword__email_email(let lhsEmail), .m_resetPassword__email_email(let rhsEmail)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEmail, rhs: rhsEmail, with: matcher), lhsEmail, rhsEmail, "email")) - return Matcher.ComparisonResult(results) - - case (.m_getCookies__force_force(let lhsForce), .m_getCookies__force_force(let rhsForce)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsForce, rhs: rhsForce, with: matcher), lhsForce, rhsForce, "force")) - return Matcher.ComparisonResult(results) - - case (.m_getRegistrationFields, .m_getRegistrationFields): return .match - - case (.m_registerUser__fields_fieldsisSocial_isSocial(let lhsFields, let lhsIssocial), .m_registerUser__fields_fieldsisSocial_isSocial(let rhsFields, let rhsIssocial)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIssocial, rhs: rhsIssocial, with: matcher), lhsIssocial, rhsIssocial, "isSocial")) - return Matcher.ComparisonResult(results) - - case (.m_validateRegistrationFields__fields_fields(let lhsFields), .m_validateRegistrationFields__fields_fields(let rhsFields)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_login__username_usernamepassword_password(p0, p1): return p0.intValue + p1.intValue - case let .m_login__externalToken_externalTokenbackend_backend(p0, p1): return p0.intValue + p1.intValue - case let .m_login__ssoToken_ssoToken(p0): return p0.intValue - case let .m_resetPassword__email_email(p0): return p0.intValue - case let .m_getCookies__force_force(p0): return p0.intValue - case .m_getRegistrationFields: return 0 - case let .m_registerUser__fields_fieldsisSocial_isSocial(p0, p1): return p0.intValue + p1.intValue - case let .m_validateRegistrationFields__fields_fields(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_login__username_usernamepassword_password: return ".login(username:password:)" - case .m_login__externalToken_externalTokenbackend_backend: return ".login(externalToken:backend:)" - case .m_login__ssoToken_ssoToken: return ".login(ssoToken:)" - case .m_resetPassword__email_email: return ".resetPassword(email:)" - case .m_getCookies__force_force: return ".getCookies(force:)" - case .m_getRegistrationFields: return ".getRegistrationFields()" - case .m_registerUser__fields_fieldsisSocial_isSocial: return ".registerUser(fields:isSocial:)" - case .m_validateRegistrationFields__fields_fields: return ".validateRegistrationFields(fields:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - @discardableResult - public static func login(username: Parameter, password: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func login(ssoToken: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func resetPassword(email: Parameter, willReturn: ResetPassword...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getRegistrationFields(willReturn: [PickerFields]...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willReturn: [String: String]...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func login(ssoToken: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func login(ssoToken: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func resetPassword(email: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resetPassword(email: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (ResetPassword).self) - willProduce(stubber) - return given - } - public static func getCookies(force: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCookies(force: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func getRegistrationFields(willThrow: Error...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getRegistrationFields(willProduce: (StubberThrows<[PickerFields]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([PickerFields]).self) - willProduce(stubber) - return given - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willProduce: (StubberThrows<[String: String]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([String: String]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - @discardableResult - public static func login(username: Parameter, password: Parameter) -> Verify { return Verify(method: .m_login__username_usernamepassword_password(`username`, `password`))} - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter) -> Verify { return Verify(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`))} - public static func login(ssoToken: Parameter) -> Verify { return Verify(method: .m_login__ssoToken_ssoToken(`ssoToken`))} - public static func resetPassword(email: Parameter) -> Verify { return Verify(method: .m_resetPassword__email_email(`email`))} - public static func getCookies(force: Parameter) -> Verify { return Verify(method: .m_getCookies__force_force(`force`))} - public static func getRegistrationFields() -> Verify { return Verify(method: .m_getRegistrationFields)} - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter) -> Verify { return Verify(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`))} - public static func validateRegistrationFields(fields: Parameter<[String: String]>) -> Verify { return Verify(method: .m_validateRegistrationFields__fields_fields(`fields`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - @discardableResult - public static func login(username: Parameter, password: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__username_usernamepassword_password(`username`, `password`), performs: perform) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), performs: perform) - } - public static func login(ssoToken: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_login__ssoToken_ssoToken(`ssoToken`), performs: perform) - } - public static func resetPassword(email: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_resetPassword__email_email(`email`), performs: perform) - } - public static func getCookies(force: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_getCookies__force_force(`force`), performs: perform) - } - public static func getRegistrationFields(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getRegistrationFields, performs: perform) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, perform: @escaping ([String: String], Bool) -> Void) -> Perform { - return Perform(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), performs: perform) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, perform: @escaping ([String: String]) -> Void) -> Perform { - return Perform(method: .m_validateRegistrationFields__fields_fields(`fields`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - BaseRouter -@MainActor -open class BaseRouterMock: BaseRouter, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func backToRoot(animated: Bool) { - addInvocation(.m_backToRoot__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_backToRoot__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func back(animated: Bool) { - addInvocation(.m_back__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_back__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func backWithFade() { - addInvocation(.m_backWithFade) - let perform = methodPerformValue(.m_backWithFade) as? () -> Void - perform?() - } - - open func dismiss(animated: Bool) { - addInvocation(.m_dismiss__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_dismiss__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func removeLastView(controllers: Int) { - addInvocation(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) - let perform = methodPerformValue(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) as? (Int) -> Void - perform?(`controllers`) - } - - open func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { - addInvocation(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) - let perform = methodPerformValue(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) as? (LogistrationSourceScreen, PostLoginData?) -> Void - perform?(`sourceScreen`, `postLoginData`) - } - - open func showStartupScreen() { - addInvocation(.m_showStartupScreen) - let perform = methodPerformValue(.m_showStartupScreen) as? () -> Void - perform?() - } - - open func showLoginScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showForgotPasswordScreen() { - addInvocation(.m_showForgotPasswordScreen) - let perform = methodPerformValue(.m_showForgotPasswordScreen) as? () -> Void - perform?() - } - - open func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) as? (String?, LogistrationSourceScreen) -> Void - perform?(`searchQuery`, `sourceScreen`) - } - - open func showWebBrowser(title: String, url: URL) { - addInvocation(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) - let perform = methodPerformValue(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) as? (String, URL) -> Void - perform?(`title`, `url`) - } - - open func showSSOWebBrowser(title: String) { - addInvocation(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) - let perform = methodPerformValue(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) as? (String) -> Void - perform?(`title`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) as? (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void - perform?(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) as? (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void - perform?(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { - addInvocation(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) as? (UIModalTransitionStyle, any View, (() -> Void)?) -> Void - perform?(`transitionStyle`, `view`, `completion`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { - addInvocation(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) as? (UIModalTransitionStyle, Bool, () -> any View) -> Void - perform?(`transitionStyle`, `animated`, `content`) - } - - - fileprivate enum MethodType { - case m_backToRoot__animated_animated(Parameter) - case m_back__animated_animated(Parameter) - case m_backWithFade - case m_dismiss__animated_animated(Parameter) - case m_removeLastView__controllers_controllers(Parameter) - case m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter, Parameter) - case m_showStartupScreen - case m_showLoginScreen__sourceScreen_sourceScreen(Parameter) - case m_showRegisterScreen__sourceScreen_sourceScreen(Parameter) - case m_showForgotPasswordScreen - case m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter, Parameter) - case m_showWebBrowser__title_titleurl_url(Parameter, Parameter) - case m_showSSOWebBrowser__title_title(Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter<() -> Void>) - case m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter, Parameter, Parameter<(() -> Void)?>) - case m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter, Parameter, Parameter<() -> any View>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_backToRoot__animated_animated(let lhsAnimated), .m_backToRoot__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_back__animated_animated(let lhsAnimated), .m_back__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_backWithFade, .m_backWithFade): return .match - - case (.m_dismiss__animated_animated(let lhsAnimated), .m_dismiss__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_removeLastView__controllers_controllers(let lhsControllers), .m_removeLastView__controllers_controllers(let rhsControllers)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsControllers, rhs: rhsControllers, with: matcher), lhsControllers, rhsControllers, "controllers")) - return Matcher.ComparisonResult(results) - - case (.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let lhsSourcescreen, let lhsPostlogindata), .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let rhsSourcescreen, let rhsPostlogindata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPostlogindata, rhs: rhsPostlogindata, with: matcher), lhsPostlogindata, rhsPostlogindata, "postLoginData")) - return Matcher.ComparisonResult(results) - - case (.m_showStartupScreen, .m_showStartupScreen): return .match - - case (.m_showLoginScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showLoginScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showRegisterScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showRegisterScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showForgotPasswordScreen, .m_showForgotPasswordScreen): return .match - - case (.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let lhsSearchquery, let lhsSourcescreen), .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let rhsSearchquery, let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchquery, rhs: rhsSearchquery, with: matcher), lhsSearchquery, rhsSearchquery, "searchQuery")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showWebBrowser__title_titleurl_url(let lhsTitle, let lhsUrl), .m_showWebBrowser__title_titleurl_url(let rhsTitle, let rhsUrl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - return Matcher.ComparisonResult(results) - - case (.m_showSSOWebBrowser__title_title(let lhsTitle), .m_showSSOWebBrowser__title_title(let rhsTitle)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let lhsAlerttitle, let lhsAlertmessage, let lhsPositiveaction, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsType), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let rhsAlerttitle, let rhsAlertmessage, let rhsPositiveaction, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPositiveaction, rhs: rhsPositiveaction, with: matcher), lhsPositiveaction, rhsPositiveaction, "positiveAction")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let lhsAlerttitle, let lhsAlertmessage, let lhsNextsectionname, let lhsAction, let lhsImage, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsNextsectiontapped), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let rhsAlerttitle, let rhsAlertmessage, let rhsNextsectionname, let rhsAction, let rhsImage, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsNextsectiontapped)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectionname, rhs: rhsNextsectionname, with: matcher), lhsNextsectionname, rhsNextsectionname, "nextSectionName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsImage, rhs: rhsImage, with: matcher), lhsImage, rhsImage, "image")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectiontapped, rhs: rhsNextsectiontapped, with: matcher), lhsNextsectiontapped, rhsNextsectiontapped, "nextSectionTapped")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let lhsTransitionstyle, let lhsView, let lhsCompletion), .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let rhsTransitionstyle, let rhsView, let rhsCompletion)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsView, rhs: rhsView, with: matcher), lhsView, rhsView, "view")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCompletion, rhs: rhsCompletion, with: matcher), lhsCompletion, rhsCompletion, "completion")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let lhsTransitionstyle, let lhsAnimated, let lhsContent), .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let rhsTransitionstyle, let rhsAnimated, let rhsContent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsContent, rhs: rhsContent, with: matcher), lhsContent, rhsContent, "content")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_backToRoot__animated_animated(p0): return p0.intValue - case let .m_back__animated_animated(p0): return p0.intValue - case .m_backWithFade: return 0 - case let .m_dismiss__animated_animated(p0): return p0.intValue - case let .m_removeLastView__controllers_controllers(p0): return p0.intValue - case let .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(p0, p1): return p0.intValue + p1.intValue - case .m_showStartupScreen: return 0 - case let .m_showLoginScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case let .m_showRegisterScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case .m_showForgotPasswordScreen: return 0 - case let .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(p0, p1): return p0.intValue + p1.intValue - case let .m_showWebBrowser__title_titleurl_url(p0, p1): return p0.intValue + p1.intValue - case let .m_showSSOWebBrowser__title_title(p0): return p0.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(p0, p1, p2, p3, p4, p5, p6, p7): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue + p7.intValue - case let .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_backToRoot__animated_animated: return ".backToRoot(animated:)" - case .m_back__animated_animated: return ".back(animated:)" - case .m_backWithFade: return ".backWithFade()" - case .m_dismiss__animated_animated: return ".dismiss(animated:)" - case .m_removeLastView__controllers_controllers: return ".removeLastView(controllers:)" - case .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData: return ".showMainOrWhatsNewScreen(sourceScreen:postLoginData:)" - case .m_showStartupScreen: return ".showStartupScreen()" - case .m_showLoginScreen__sourceScreen_sourceScreen: return ".showLoginScreen(sourceScreen:)" - case .m_showRegisterScreen__sourceScreen_sourceScreen: return ".showRegisterScreen(sourceScreen:)" - case .m_showForgotPasswordScreen: return ".showForgotPasswordScreen()" - case .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen: return ".showDiscoveryScreen(searchQuery:sourceScreen:)" - case .m_showWebBrowser__title_titleurl_url: return ".showWebBrowser(title:url:)" - case .m_showSSOWebBrowser__title_title: return ".showSSOWebBrowser(title:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type: return ".presentAlert(alertTitle:alertMessage:positiveAction:onCloseTapped:firstButtonTapped:type:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped: return ".presentAlert(alertTitle:alertMessage:nextSectionName:action:image:onCloseTapped:firstButtonTapped:nextSectionTapped:)" - case .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion: return ".presentView(transitionStyle:view:completion:)" - case .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content: return ".presentView(transitionStyle:animated:content:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func backToRoot(animated: Parameter) -> Verify { return Verify(method: .m_backToRoot__animated_animated(`animated`))} - public static func back(animated: Parameter) -> Verify { return Verify(method: .m_back__animated_animated(`animated`))} - public static func backWithFade() -> Verify { return Verify(method: .m_backWithFade)} - public static func dismiss(animated: Parameter) -> Verify { return Verify(method: .m_dismiss__animated_animated(`animated`))} - public static func removeLastView(controllers: Parameter) -> Verify { return Verify(method: .m_removeLastView__controllers_controllers(`controllers`))} - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter) -> Verify { return Verify(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`))} - public static func showStartupScreen() -> Verify { return Verify(method: .m_showStartupScreen)} - public static func showLoginScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showRegisterScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showForgotPasswordScreen() -> Verify { return Verify(method: .m_showForgotPasswordScreen)} - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter) -> Verify { return Verify(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`))} - public static func showWebBrowser(title: Parameter, url: Parameter) -> Verify { return Verify(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`))} - public static func showSSOWebBrowser(title: Parameter) -> Verify { return Verify(method: .m_showSSOWebBrowser__title_title(`title`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`))} - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`))} - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func backToRoot(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_backToRoot__animated_animated(`animated`), performs: perform) - } - public static func back(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_back__animated_animated(`animated`), performs: perform) - } - public static func backWithFade(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_backWithFade, performs: perform) - } - public static func dismiss(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_dismiss__animated_animated(`animated`), performs: perform) - } - public static func removeLastView(controllers: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_removeLastView__controllers_controllers(`controllers`), performs: perform) - } - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter, perform: @escaping (LogistrationSourceScreen, PostLoginData?) -> Void) -> Perform { - return Perform(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`), performs: perform) - } - public static func showStartupScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showStartupScreen, performs: perform) - } - public static func showLoginScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showRegisterScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showForgotPasswordScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showForgotPasswordScreen, performs: perform) - } - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter, perform: @escaping (String?, LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`), performs: perform) - } - public static func showWebBrowser(title: Parameter, url: Parameter, perform: @escaping (String, URL) -> Void) -> Perform { - return Perform(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`), performs: perform) - } - public static func showSSOWebBrowser(title: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showSSOWebBrowser__title_title(`title`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter, perform: @escaping (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>, perform: @escaping (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>, perform: @escaping (UIModalTransitionStyle, any View, (() -> Void)?) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>, perform: @escaping (UIModalTransitionStyle, Bool, () -> any View) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CalendarManagerProtocol -@MainActor -open class CalendarManagerProtocolMock: CalendarManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func createCalendarIfNeeded() { - addInvocation(.m_createCalendarIfNeeded) - let perform = methodPerformValue(.m_createCalendarIfNeeded) as? () -> Void - perform?() - } - - open func filterCoursesBySelected(fetchedCourses: [CourseForSync]) -> [CourseForSync] { - addInvocation(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) - let perform = methodPerformValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) as? ([CourseForSync]) -> Void - perform?(`fetchedCourses`) - var __value: [CourseForSync] - do { - __value = try methodReturnValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))).casted() - } catch { - onFatalFailure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - Failure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - } - return __value - } - - open func removeOldCalendar() { - addInvocation(.m_removeOldCalendar) - let perform = methodPerformValue(.m_removeOldCalendar) as? () -> Void - perform?() - } - - open func removeOutdatedEvents(courseID: String) { - addInvocation(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - } - - open func syncCourse(courseID: String, courseName: String, dates: CourseDates) { - addInvocation(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) - let perform = methodPerformValue(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) as? (String, String, CourseDates) -> Void - perform?(`courseID`, `courseName`, `dates`) - } - - open func requestAccess() -> Bool { - addInvocation(.m_requestAccess) - let perform = methodPerformValue(.m_requestAccess) as? () -> Void - perform?() - var __value: Bool - do { - __value = try methodReturnValue(.m_requestAccess).casted() - } catch { - onFatalFailure("Stub return value not specified for requestAccess(). Use given") - Failure("Stub return value not specified for requestAccess(). Use given") - } - return __value - } - - open func courseStatus(courseID: String) -> SyncStatus { - addInvocation(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: SyncStatus - do { - __value = try methodReturnValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for courseStatus(courseID: String). Use given") - Failure("Stub return value not specified for courseStatus(courseID: String). Use given") - } - return __value - } - - open func clearAllData(removeCalendar: Bool) { - addInvocation(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) - let perform = methodPerformValue(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) as? (Bool) -> Void - perform?(`removeCalendar`) - } - - open func isDatesChanged(courseID: String, checksum: String) -> Bool { - addInvocation(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) - let perform = methodPerformValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) as? (String, String) -> Void - perform?(`courseID`, `checksum`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - Failure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - } - return __value - } - - - fileprivate enum MethodType { - case m_createCalendarIfNeeded - case m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>) - case m_removeOldCalendar - case m_removeOutdatedEvents__courseID_courseID(Parameter) - case m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter, Parameter, Parameter) - case m_requestAccess - case m_courseStatus__courseID_courseID(Parameter) - case m_clearAllData__removeCalendar_removeCalendar(Parameter) - case m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_createCalendarIfNeeded, .m_createCalendarIfNeeded): return .match - - case (.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let lhsFetchedcourses), .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let rhsFetchedcourses)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFetchedcourses, rhs: rhsFetchedcourses, with: matcher), lhsFetchedcourses, rhsFetchedcourses, "fetchedCourses")) - return Matcher.ComparisonResult(results) - - case (.m_removeOldCalendar, .m_removeOldCalendar): return .match - - case (.m_removeOutdatedEvents__courseID_courseID(let lhsCourseid), .m_removeOutdatedEvents__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let lhsCourseid, let lhsCoursename, let lhsDates), .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let rhsCourseid, let rhsCoursename, let rhsDates)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDates, rhs: rhsDates, with: matcher), lhsDates, rhsDates, "dates")) - return Matcher.ComparisonResult(results) - - case (.m_requestAccess, .m_requestAccess): return .match - - case (.m_courseStatus__courseID_courseID(let lhsCourseid), .m_courseStatus__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_clearAllData__removeCalendar_removeCalendar(let lhsRemovecalendar), .m_clearAllData__removeCalendar_removeCalendar(let rhsRemovecalendar)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRemovecalendar, rhs: rhsRemovecalendar, with: matcher), lhsRemovecalendar, rhsRemovecalendar, "removeCalendar")) - return Matcher.ComparisonResult(results) - - case (.m_isDatesChanged__courseID_courseIDchecksum_checksum(let lhsCourseid, let lhsChecksum), .m_isDatesChanged__courseID_courseIDchecksum_checksum(let rhsCourseid, let rhsChecksum)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsChecksum, rhs: rhsChecksum, with: matcher), lhsChecksum, rhsChecksum, "checksum")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_createCalendarIfNeeded: return 0 - case let .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(p0): return p0.intValue - case .m_removeOldCalendar: return 0 - case let .m_removeOutdatedEvents__courseID_courseID(p0): return p0.intValue - case let .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case .m_requestAccess: return 0 - case let .m_courseStatus__courseID_courseID(p0): return p0.intValue - case let .m_clearAllData__removeCalendar_removeCalendar(p0): return p0.intValue - case let .m_isDatesChanged__courseID_courseIDchecksum_checksum(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_createCalendarIfNeeded: return ".createCalendarIfNeeded()" - case .m_filterCoursesBySelected__fetchedCourses_fetchedCourses: return ".filterCoursesBySelected(fetchedCourses:)" - case .m_removeOldCalendar: return ".removeOldCalendar()" - case .m_removeOutdatedEvents__courseID_courseID: return ".removeOutdatedEvents(courseID:)" - case .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates: return ".syncCourse(courseID:courseName:dates:)" - case .m_requestAccess: return ".requestAccess()" - case .m_courseStatus__courseID_courseID: return ".courseStatus(courseID:)" - case .m_clearAllData__removeCalendar_removeCalendar: return ".clearAllData(removeCalendar:)" - case .m_isDatesChanged__courseID_courseIDchecksum_checksum: return ".isDatesChanged(courseID:checksum:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willReturn: [CourseForSync]...) -> MethodStub { - return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func requestAccess(willReturn: Bool...) -> MethodStub { - return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func courseStatus(courseID: Parameter, willReturn: SyncStatus...) -> MethodStub { - return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willProduce: (Stubber<[CourseForSync]>) -> Void) -> MethodStub { - let willReturn: [[CourseForSync]] = [] - let given: Given = { return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([CourseForSync]).self) - willProduce(stubber) - return given - } - public static func requestAccess(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func courseStatus(courseID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [SyncStatus] = [] - let given: Given = { return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (SyncStatus).self) - willProduce(stubber) - return given - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func createCalendarIfNeeded() -> Verify { return Verify(method: .m_createCalendarIfNeeded)} - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>) -> Verify { return Verify(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`))} - public static func removeOldCalendar() -> Verify { return Verify(method: .m_removeOldCalendar)} - public static func removeOutdatedEvents(courseID: Parameter) -> Verify { return Verify(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`))} - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter) -> Verify { return Verify(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`))} - public static func requestAccess() -> Verify { return Verify(method: .m_requestAccess)} - public static func courseStatus(courseID: Parameter) -> Verify { return Verify(method: .m_courseStatus__courseID_courseID(`courseID`))} - public static func clearAllData(removeCalendar: Parameter) -> Verify { return Verify(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`))} - public static func isDatesChanged(courseID: Parameter, checksum: Parameter) -> Verify { return Verify(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func createCalendarIfNeeded(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_createCalendarIfNeeded, performs: perform) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, perform: @escaping ([CourseForSync]) -> Void) -> Perform { - return Perform(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), performs: perform) - } - public static func removeOldCalendar(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeOldCalendar, performs: perform) - } - public static func removeOutdatedEvents(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`), performs: perform) - } - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter, perform: @escaping (String, String, CourseDates) -> Void) -> Perform { - return Perform(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`), performs: perform) - } - public static func requestAccess(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_requestAccess, performs: perform) - } - public static func courseStatus(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_courseStatus__courseID_courseID(`courseID`), performs: perform) - } - public static func clearAllData(removeCalendar: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`), performs: perform) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConfigProtocol - -open class ConfigProtocolMock: ConfigProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var baseURL: URL { - get { invocations.append(.p_baseURL_get); return __p_baseURL ?? givenGetterValue(.p_baseURL_get, "ConfigProtocolMock - stub value for baseURL was not defined") } - } - private var __p_baseURL: (URL)? - - public var baseSSOURL: URL { - get { invocations.append(.p_baseSSOURL_get); return __p_baseSSOURL ?? givenGetterValue(.p_baseSSOURL_get, "ConfigProtocolMock - stub value for baseSSOURL was not defined") } - } - private var __p_baseSSOURL: (URL)? - - public var ssoFinishedURL: URL { - get { invocations.append(.p_ssoFinishedURL_get); return __p_ssoFinishedURL ?? givenGetterValue(.p_ssoFinishedURL_get, "ConfigProtocolMock - stub value for ssoFinishedURL was not defined") } - } - private var __p_ssoFinishedURL: (URL)? - - public var ssoButtonTitle: [String: Any] { - get { invocations.append(.p_ssoButtonTitle_get); return __p_ssoButtonTitle ?? givenGetterValue(.p_ssoButtonTitle_get, "ConfigProtocolMock - stub value for ssoButtonTitle was not defined") } - } - private var __p_ssoButtonTitle: ([String: Any])? - - public var oAuthClientId: String { - get { invocations.append(.p_oAuthClientId_get); return __p_oAuthClientId ?? givenGetterValue(.p_oAuthClientId_get, "ConfigProtocolMock - stub value for oAuthClientId was not defined") } - } - private var __p_oAuthClientId: (String)? - - public var tokenType: TokenType { - get { invocations.append(.p_tokenType_get); return __p_tokenType ?? givenGetterValue(.p_tokenType_get, "ConfigProtocolMock - stub value for tokenType was not defined") } - } - private var __p_tokenType: (TokenType)? - - public var feedbackEmail: String { - get { invocations.append(.p_feedbackEmail_get); return __p_feedbackEmail ?? givenGetterValue(.p_feedbackEmail_get, "ConfigProtocolMock - stub value for feedbackEmail was not defined") } - } - private var __p_feedbackEmail: (String)? - - public var appStoreLink: String { - get { invocations.append(.p_appStoreLink_get); return __p_appStoreLink ?? givenGetterValue(.p_appStoreLink_get, "ConfigProtocolMock - stub value for appStoreLink was not defined") } - } - private var __p_appStoreLink: (String)? - - public var faq: URL? { - get { invocations.append(.p_faq_get); return __p_faq ?? optionalGivenGetterValue(.p_faq_get, "ConfigProtocolMock - stub value for faq was not defined") } - } - private var __p_faq: (URL)? - - public var platformName: String { - get { invocations.append(.p_platformName_get); return __p_platformName ?? givenGetterValue(.p_platformName_get, "ConfigProtocolMock - stub value for platformName was not defined") } - } - private var __p_platformName: (String)? - - public var agreement: AgreementConfig { - get { invocations.append(.p_agreement_get); return __p_agreement ?? givenGetterValue(.p_agreement_get, "ConfigProtocolMock - stub value for agreement was not defined") } - } - private var __p_agreement: (AgreementConfig)? - - public var firebase: FirebaseConfig { - get { invocations.append(.p_firebase_get); return __p_firebase ?? givenGetterValue(.p_firebase_get, "ConfigProtocolMock - stub value for firebase was not defined") } - } - private var __p_firebase: (FirebaseConfig)? - - public var facebook: FacebookConfig { - get { invocations.append(.p_facebook_get); return __p_facebook ?? givenGetterValue(.p_facebook_get, "ConfigProtocolMock - stub value for facebook was not defined") } - } - private var __p_facebook: (FacebookConfig)? - - public var microsoft: MicrosoftConfig { - get { invocations.append(.p_microsoft_get); return __p_microsoft ?? givenGetterValue(.p_microsoft_get, "ConfigProtocolMock - stub value for microsoft was not defined") } - } - private var __p_microsoft: (MicrosoftConfig)? - - public var google: GoogleConfig { - get { invocations.append(.p_google_get); return __p_google ?? givenGetterValue(.p_google_get, "ConfigProtocolMock - stub value for google was not defined") } - } - private var __p_google: (GoogleConfig)? - - public var appleSignIn: AppleSignInConfig { - get { invocations.append(.p_appleSignIn_get); return __p_appleSignIn ?? givenGetterValue(.p_appleSignIn_get, "ConfigProtocolMock - stub value for appleSignIn was not defined") } - } - private var __p_appleSignIn: (AppleSignInConfig)? - - public var features: FeaturesConfig { - get { invocations.append(.p_features_get); return __p_features ?? givenGetterValue(.p_features_get, "ConfigProtocolMock - stub value for features was not defined") } - } - private var __p_features: (FeaturesConfig)? - - public var theme: ThemeConfig { - get { invocations.append(.p_theme_get); return __p_theme ?? givenGetterValue(.p_theme_get, "ConfigProtocolMock - stub value for theme was not defined") } - } - private var __p_theme: (ThemeConfig)? - - public var uiComponents: UIComponentsConfig { - get { invocations.append(.p_uiComponents_get); return __p_uiComponents ?? givenGetterValue(.p_uiComponents_get, "ConfigProtocolMock - stub value for uiComponents was not defined") } - } - private var __p_uiComponents: (UIComponentsConfig)? - - public var discovery: DiscoveryConfig { - get { invocations.append(.p_discovery_get); return __p_discovery ?? givenGetterValue(.p_discovery_get, "ConfigProtocolMock - stub value for discovery was not defined") } - } - private var __p_discovery: (DiscoveryConfig)? - - public var dashboard: DashboardConfig { - get { invocations.append(.p_dashboard_get); return __p_dashboard ?? givenGetterValue(.p_dashboard_get, "ConfigProtocolMock - stub value for dashboard was not defined") } - } - private var __p_dashboard: (DashboardConfig)? - - public var braze: BrazeConfig { - get { invocations.append(.p_braze_get); return __p_braze ?? givenGetterValue(.p_braze_get, "ConfigProtocolMock - stub value for braze was not defined") } - } - private var __p_braze: (BrazeConfig)? - - public var branch: BranchConfig { - get { invocations.append(.p_branch_get); return __p_branch ?? givenGetterValue(.p_branch_get, "ConfigProtocolMock - stub value for branch was not defined") } - } - private var __p_branch: (BranchConfig)? - - public var program: DiscoveryConfig { - get { invocations.append(.p_program_get); return __p_program ?? givenGetterValue(.p_program_get, "ConfigProtocolMock - stub value for program was not defined") } - } - private var __p_program: (DiscoveryConfig)? - - public var experimentalFeatures: ExperimentalFeaturesConfig { - get { invocations.append(.p_experimentalFeatures_get); return __p_experimentalFeatures ?? givenGetterValue(.p_experimentalFeatures_get, "ConfigProtocolMock - stub value for experimentalFeatures was not defined") } - } - private var __p_experimentalFeatures: (ExperimentalFeaturesConfig)? - - public var URIScheme: String { - get { invocations.append(.p_URIScheme_get); return __p_URIScheme ?? givenGetterValue(.p_URIScheme_get, "ConfigProtocolMock - stub value for URIScheme was not defined") } - } - private var __p_URIScheme: (String)? - - - - - - - fileprivate enum MethodType { - case p_baseURL_get - case p_baseSSOURL_get - case p_ssoFinishedURL_get - case p_ssoButtonTitle_get - case p_oAuthClientId_get - case p_tokenType_get - case p_feedbackEmail_get - case p_appStoreLink_get - case p_faq_get - case p_platformName_get - case p_agreement_get - case p_firebase_get - case p_facebook_get - case p_microsoft_get - case p_google_get - case p_appleSignIn_get - case p_features_get - case p_theme_get - case p_uiComponents_get - case p_discovery_get - case p_dashboard_get - case p_braze_get - case p_branch_get - case p_program_get - case p_experimentalFeatures_get - case p_URIScheme_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_baseURL_get,.p_baseURL_get): return Matcher.ComparisonResult.match - case (.p_baseSSOURL_get,.p_baseSSOURL_get): return Matcher.ComparisonResult.match - case (.p_ssoFinishedURL_get,.p_ssoFinishedURL_get): return Matcher.ComparisonResult.match - case (.p_ssoButtonTitle_get,.p_ssoButtonTitle_get): return Matcher.ComparisonResult.match - case (.p_oAuthClientId_get,.p_oAuthClientId_get): return Matcher.ComparisonResult.match - case (.p_tokenType_get,.p_tokenType_get): return Matcher.ComparisonResult.match - case (.p_feedbackEmail_get,.p_feedbackEmail_get): return Matcher.ComparisonResult.match - case (.p_appStoreLink_get,.p_appStoreLink_get): return Matcher.ComparisonResult.match - case (.p_faq_get,.p_faq_get): return Matcher.ComparisonResult.match - case (.p_platformName_get,.p_platformName_get): return Matcher.ComparisonResult.match - case (.p_agreement_get,.p_agreement_get): return Matcher.ComparisonResult.match - case (.p_firebase_get,.p_firebase_get): return Matcher.ComparisonResult.match - case (.p_facebook_get,.p_facebook_get): return Matcher.ComparisonResult.match - case (.p_microsoft_get,.p_microsoft_get): return Matcher.ComparisonResult.match - case (.p_google_get,.p_google_get): return Matcher.ComparisonResult.match - case (.p_appleSignIn_get,.p_appleSignIn_get): return Matcher.ComparisonResult.match - case (.p_features_get,.p_features_get): return Matcher.ComparisonResult.match - case (.p_theme_get,.p_theme_get): return Matcher.ComparisonResult.match - case (.p_uiComponents_get,.p_uiComponents_get): return Matcher.ComparisonResult.match - case (.p_discovery_get,.p_discovery_get): return Matcher.ComparisonResult.match - case (.p_dashboard_get,.p_dashboard_get): return Matcher.ComparisonResult.match - case (.p_braze_get,.p_braze_get): return Matcher.ComparisonResult.match - case (.p_branch_get,.p_branch_get): return Matcher.ComparisonResult.match - case (.p_program_get,.p_program_get): return Matcher.ComparisonResult.match - case (.p_experimentalFeatures_get,.p_experimentalFeatures_get): return Matcher.ComparisonResult.match - case (.p_URIScheme_get,.p_URIScheme_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_baseURL_get: return 0 - case .p_baseSSOURL_get: return 0 - case .p_ssoFinishedURL_get: return 0 - case .p_ssoButtonTitle_get: return 0 - case .p_oAuthClientId_get: return 0 - case .p_tokenType_get: return 0 - case .p_feedbackEmail_get: return 0 - case .p_appStoreLink_get: return 0 - case .p_faq_get: return 0 - case .p_platformName_get: return 0 - case .p_agreement_get: return 0 - case .p_firebase_get: return 0 - case .p_facebook_get: return 0 - case .p_microsoft_get: return 0 - case .p_google_get: return 0 - case .p_appleSignIn_get: return 0 - case .p_features_get: return 0 - case .p_theme_get: return 0 - case .p_uiComponents_get: return 0 - case .p_discovery_get: return 0 - case .p_dashboard_get: return 0 - case .p_braze_get: return 0 - case .p_branch_get: return 0 - case .p_program_get: return 0 - case .p_experimentalFeatures_get: return 0 - case .p_URIScheme_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_baseURL_get: return "[get] .baseURL" - case .p_baseSSOURL_get: return "[get] .baseSSOURL" - case .p_ssoFinishedURL_get: return "[get] .ssoFinishedURL" - case .p_ssoButtonTitle_get: return "[get] .ssoButtonTitle" - case .p_oAuthClientId_get: return "[get] .oAuthClientId" - case .p_tokenType_get: return "[get] .tokenType" - case .p_feedbackEmail_get: return "[get] .feedbackEmail" - case .p_appStoreLink_get: return "[get] .appStoreLink" - case .p_faq_get: return "[get] .faq" - case .p_platformName_get: return "[get] .platformName" - case .p_agreement_get: return "[get] .agreement" - case .p_firebase_get: return "[get] .firebase" - case .p_facebook_get: return "[get] .facebook" - case .p_microsoft_get: return "[get] .microsoft" - case .p_google_get: return "[get] .google" - case .p_appleSignIn_get: return "[get] .appleSignIn" - case .p_features_get: return "[get] .features" - case .p_theme_get: return "[get] .theme" - case .p_uiComponents_get: return "[get] .uiComponents" - case .p_discovery_get: return "[get] .discovery" - case .p_dashboard_get: return "[get] .dashboard" - case .p_braze_get: return "[get] .braze" - case .p_branch_get: return "[get] .branch" - case .p_program_get: return "[get] .program" - case .p_experimentalFeatures_get: return "[get] .experimentalFeatures" - case .p_URIScheme_get: return "[get] .URIScheme" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func baseURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func baseSSOURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseSSOURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoFinishedURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_ssoFinishedURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoButtonTitle(getter defaultValue: [String: Any]...) -> PropertyStub { - return Given(method: .p_ssoButtonTitle_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func oAuthClientId(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_oAuthClientId_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func tokenType(getter defaultValue: TokenType...) -> PropertyStub { - return Given(method: .p_tokenType_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func feedbackEmail(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_feedbackEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appStoreLink(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_appStoreLink_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func faq(getter defaultValue: URL?...) -> PropertyStub { - return Given(method: .p_faq_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func platformName(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_platformName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func agreement(getter defaultValue: AgreementConfig...) -> PropertyStub { - return Given(method: .p_agreement_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func firebase(getter defaultValue: FirebaseConfig...) -> PropertyStub { - return Given(method: .p_firebase_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func facebook(getter defaultValue: FacebookConfig...) -> PropertyStub { - return Given(method: .p_facebook_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func microsoft(getter defaultValue: MicrosoftConfig...) -> PropertyStub { - return Given(method: .p_microsoft_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func google(getter defaultValue: GoogleConfig...) -> PropertyStub { - return Given(method: .p_google_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignIn(getter defaultValue: AppleSignInConfig...) -> PropertyStub { - return Given(method: .p_appleSignIn_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func features(getter defaultValue: FeaturesConfig...) -> PropertyStub { - return Given(method: .p_features_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func theme(getter defaultValue: ThemeConfig...) -> PropertyStub { - return Given(method: .p_theme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func uiComponents(getter defaultValue: UIComponentsConfig...) -> PropertyStub { - return Given(method: .p_uiComponents_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func discovery(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_discovery_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func dashboard(getter defaultValue: DashboardConfig...) -> PropertyStub { - return Given(method: .p_dashboard_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func braze(getter defaultValue: BrazeConfig...) -> PropertyStub { - return Given(method: .p_braze_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func branch(getter defaultValue: BranchConfig...) -> PropertyStub { - return Given(method: .p_branch_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func program(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_program_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func experimentalFeatures(getter defaultValue: ExperimentalFeaturesConfig...) -> PropertyStub { - return Given(method: .p_experimentalFeatures_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func URIScheme(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_URIScheme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var baseURL: Verify { return Verify(method: .p_baseURL_get) } - public static var baseSSOURL: Verify { return Verify(method: .p_baseSSOURL_get) } - public static var ssoFinishedURL: Verify { return Verify(method: .p_ssoFinishedURL_get) } - public static var ssoButtonTitle: Verify { return Verify(method: .p_ssoButtonTitle_get) } - public static var oAuthClientId: Verify { return Verify(method: .p_oAuthClientId_get) } - public static var tokenType: Verify { return Verify(method: .p_tokenType_get) } - public static var feedbackEmail: Verify { return Verify(method: .p_feedbackEmail_get) } - public static var appStoreLink: Verify { return Verify(method: .p_appStoreLink_get) } - public static var faq: Verify { return Verify(method: .p_faq_get) } - public static var platformName: Verify { return Verify(method: .p_platformName_get) } - public static var agreement: Verify { return Verify(method: .p_agreement_get) } - public static var firebase: Verify { return Verify(method: .p_firebase_get) } - public static var facebook: Verify { return Verify(method: .p_facebook_get) } - public static var microsoft: Verify { return Verify(method: .p_microsoft_get) } - public static var google: Verify { return Verify(method: .p_google_get) } - public static var appleSignIn: Verify { return Verify(method: .p_appleSignIn_get) } - public static var features: Verify { return Verify(method: .p_features_get) } - public static var theme: Verify { return Verify(method: .p_theme_get) } - public static var uiComponents: Verify { return Verify(method: .p_uiComponents_get) } - public static var discovery: Verify { return Verify(method: .p_discovery_get) } - public static var dashboard: Verify { return Verify(method: .p_dashboard_get) } - public static var braze: Verify { return Verify(method: .p_braze_get) } - public static var branch: Verify { return Verify(method: .p_branch_get) } - public static var program: Verify { return Verify(method: .p_program_get) } - public static var experimentalFeatures: Verify { return Verify(method: .p_experimentalFeatures_get) } - public static var URIScheme: Verify { return Verify(method: .p_URIScheme_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConnectivityProtocol -@MainActor -open class ConnectivityProtocolMock: ConnectivityProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var isInternetAvaliable: Bool { - get { invocations.append(.p_isInternetAvaliable_get); return __p_isInternetAvaliable ?? givenGetterValue(.p_isInternetAvaliable_get, "ConnectivityProtocolMock - stub value for isInternetAvaliable was not defined") } - } - private var __p_isInternetAvaliable: (Bool)? - - public var isMobileData: Bool { - get { invocations.append(.p_isMobileData_get); return __p_isMobileData ?? givenGetterValue(.p_isMobileData_get, "ConnectivityProtocolMock - stub value for isMobileData was not defined") } - } - private var __p_isMobileData: (Bool)? - - public var internetReachableSubject: CurrentValueSubject { - get { invocations.append(.p_internetReachableSubject_get); return __p_internetReachableSubject ?? givenGetterValue(.p_internetReachableSubject_get, "ConnectivityProtocolMock - stub value for internetReachableSubject was not defined") } - } - private var __p_internetReachableSubject: (CurrentValueSubject)? - - - - - - - fileprivate enum MethodType { - case p_isInternetAvaliable_get - case p_isMobileData_get - case p_internetReachableSubject_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_isInternetAvaliable_get,.p_isInternetAvaliable_get): return Matcher.ComparisonResult.match - case (.p_isMobileData_get,.p_isMobileData_get): return Matcher.ComparisonResult.match - case (.p_internetReachableSubject_get,.p_internetReachableSubject_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_isInternetAvaliable_get: return 0 - case .p_isMobileData_get: return 0 - case .p_internetReachableSubject_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_isInternetAvaliable_get: return "[get] .isInternetAvaliable" - case .p_isMobileData_get: return "[get] .isMobileData" - case .p_internetReachableSubject_get: return "[get] .internetReachableSubject" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func isInternetAvaliable(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isInternetAvaliable_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func isMobileData(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isMobileData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func internetReachableSubject(getter defaultValue: CurrentValueSubject...) -> PropertyStub { - return Given(method: .p_internetReachableSubject_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var isInternetAvaliable: Verify { return Verify(method: .p_isInternetAvaliable_get) } - public static var isMobileData: Verify { return Verify(method: .p_isMobileData_get) } - public static var internetReachableSubject: Verify { return Verify(method: .p_internetReachableSubject_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreAnalytics - -open class CoreAnalyticsMock: CoreAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { - addInvocation(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) - let perform = methodPerformValue(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) as? (AnalyticsEvent, EventBIValue, String?, Int?) -> Void - perform?(`event`, `biValue`, `action`, `rating`) - } - - open func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { - addInvocation(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) - let perform = methodPerformValue(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) as? (AnalyticsEvent, EventBIValue, String, String) -> Void - perform?(`event`, `bivalue`, `value`, `oldValue`) - } - - open func trackEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackScreenEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackScreenEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - - fileprivate enum MethodType { - case m_trackEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter, Parameter, Parameter, Parameter) - case m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter, Parameter, Parameter, Parameter) - case m_trackEvent__event(Parameter) - case m_trackEvent__eventbiValue_biValue(Parameter, Parameter) - case m_trackScreenEvent__event(Parameter) - case m_trackScreenEvent__eventbiValue_biValue(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_trackEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackScreenEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_appreview__eventbiValue_biValueaction_actionrating_rating(let lhsEvent, let lhsBivalue, let lhsAction, let lhsRating), .m_appreview__eventbiValue_biValueaction_actionrating_rating(let rhsEvent, let rhsBivalue, let rhsAction, let rhsRating)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRating, rhs: rhsRating, with: matcher), lhsRating, rhsRating, "rating")) - return Matcher.ComparisonResult(results) - - case (.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let lhsEvent, let lhsBivalue, let lhsValue, let lhsOldvalue), .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let rhsEvent, let rhsBivalue, let rhsValue, let rhsOldvalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "bivalue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsValue, rhs: rhsValue, with: matcher), lhsValue, rhsValue, "value")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOldvalue, rhs: rhsOldvalue, with: matcher), lhsOldvalue, rhsOldvalue, "oldValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__event(let lhsEvent), .m_trackEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__event(let lhsEvent), .m_trackScreenEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackScreenEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_trackEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_trackScreenEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_appreview__eventbiValue_biValueaction_actionrating_rating(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_trackEvent__event(p0): return p0.intValue - case let .m_trackEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__event(p0): return p0.intValue - case let .m_trackScreenEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_trackEvent__eventparameters_parameters: return ".trackEvent(_:parameters:)" - case .m_trackEvent__eventbiValue_biValueparameters_parameters: return ".trackEvent(_:biValue:parameters:)" - case .m_trackScreenEvent__eventparameters_parameters: return ".trackScreenEvent(_:parameters:)" - case .m_trackScreenEvent__eventbiValue_biValueparameters_parameters: return ".trackScreenEvent(_:biValue:parameters:)" - case .m_appreview__eventbiValue_biValueaction_actionrating_rating: return ".appreview(_:biValue:action:rating:)" - case .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue: return ".videoQualityChanged(_:bivalue:value:oldValue:)" - case .m_trackEvent__event: return ".trackEvent(_:)" - case .m_trackEvent__eventbiValue_biValue: return ".trackEvent(_:biValue:)" - case .m_trackScreenEvent__event: return ".trackScreenEvent(_:)" - case .m_trackScreenEvent__eventbiValue_biValue: return ".trackScreenEvent(_:biValue:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter) -> Verify { return Verify(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`))} - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter) -> Verify { return Verify(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`))} - public static func trackEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackEvent__event(`event`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`))} - public static func trackScreenEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__event(`event`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String?, Int?) -> Void) -> Perform { - return Perform(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`), performs: perform) - } - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String, String) -> Void) -> Perform { - return Perform(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`), performs: perform) - } - public static func trackEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackEvent__event(`event`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__event(`event`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CorePersistenceProtocol - -open class CorePersistenceProtocolMock: CorePersistenceProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func set(userId: Int) { - addInvocation(.m_set__userId_userId(Parameter.value(`userId`))) - let perform = methodPerformValue(.m_set__userId_userId(Parameter.value(`userId`))) as? (Int) -> Void - perform?(`userId`) - } - - open func getUserID() -> Int? { - addInvocation(.m_getUserID) - let perform = methodPerformValue(.m_getUserID) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getUserID).casted() - } catch { - // do nothing - } - return __value - } - - @MainActor - open func publisher() throws -> AnyPublisher { - addInvocation(.m_publisher) - let perform = methodPerformValue(.m_publisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_publisher).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for publisher(). Use given") - Failure("Stub return value not specified for publisher(). Use given") - } catch { - throw error - } - return __value - } - - open func addToDownloadQueue(tasks: [DownloadDataTask]) { - addInvocation(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) as? ([DownloadDataTask]) -> Void - perform?(`tasks`) - } - - open func saveOfflineProgress(progress: OfflineProgress) { - addInvocation(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) - let perform = methodPerformValue(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) as? (OfflineProgress) -> Void - perform?(`progress`) - } - - open func loadProgress(for blockID: String) -> OfflineProgress? { - addInvocation(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - var __value: OfflineProgress? = nil - do { - __value = try methodReturnValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))).casted() - } catch { - // do nothing - } - return __value - } - - open func loadAllOfflineProgress() -> [OfflineProgress] { - addInvocation(.m_loadAllOfflineProgress) - let perform = methodPerformValue(.m_loadAllOfflineProgress) as? () -> Void - perform?() - var __value: [OfflineProgress] - do { - __value = try methodReturnValue(.m_loadAllOfflineProgress).casted() - } catch { - onFatalFailure("Stub return value not specified for loadAllOfflineProgress(). Use given") - Failure("Stub return value not specified for loadAllOfflineProgress(). Use given") - } - return __value - } - - open func deleteProgress(for blockID: String) { - addInvocation(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - } - - open func deleteAllProgress() { - addInvocation(.m_deleteAllProgress) - let perform = methodPerformValue(.m_deleteAllProgress) as? () -> Void - perform?() - } - - open func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { - addInvocation(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) as? ([CourseBlock], DownloadQuality) -> Void - perform?(`blocks`, `downloadQuality`) - } - - open func updateTask(task: DownloadDataTask) { - addInvocation(.m_updateTask__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_updateTask__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - } - - open func downloadDataTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getDownloadDataTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasks) - let perform = methodPerformValue(.m_getDownloadDataTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasks(). Use given") - Failure("Stub return value not specified for getDownloadDataTasks(). Use given") - } - return __value - } - - open func getDownloadDataTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func deleteDownloadDataTasks(ids: [String]) { - addInvocation(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) - let perform = methodPerformValue(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) as? ([String]) -> Void - perform?(`ids`) - } - - - fileprivate enum MethodType { - case m_set__userId_userId(Parameter) - case m_getUserID - case m_publisher - case m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>) - case m_saveOfflineProgress__progress_progress(Parameter) - case m_loadProgress__for_blockID(Parameter) - case m_loadAllOfflineProgress - case m_deleteProgress__for_blockID(Parameter) - case m_deleteAllProgress - case m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>, Parameter) - case m_updateTask__task_task(Parameter) - case m_downloadDataTask__for_blockId(Parameter) - case m_getDownloadDataTasks - case m_getDownloadDataTasksForCourse__courseId(Parameter) - case m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_set__userId_userId(let lhsUserid), .m_set__userId_userId(let rhsUserid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUserid, rhs: rhsUserid, with: matcher), lhsUserid, rhsUserid, "userId")) - return Matcher.ComparisonResult(results) - - case (.m_getUserID, .m_getUserID): return .match - - case (.m_publisher, .m_publisher): return .match - - case (.m_addToDownloadQueue__tasks_tasks(let lhsTasks), .m_addToDownloadQueue__tasks_tasks(let rhsTasks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTasks, rhs: rhsTasks, with: matcher), lhsTasks, rhsTasks, "tasks")) - return Matcher.ComparisonResult(results) - - case (.m_saveOfflineProgress__progress_progress(let lhsProgress), .m_saveOfflineProgress__progress_progress(let rhsProgress)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsProgress, rhs: rhsProgress, with: matcher), lhsProgress, rhsProgress, "progress")) - return Matcher.ComparisonResult(results) - - case (.m_loadProgress__for_blockID(let lhsBlockid), .m_loadProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_loadAllOfflineProgress, .m_loadAllOfflineProgress): return .match - - case (.m_deleteProgress__for_blockID(let lhsBlockid), .m_deleteProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_deleteAllProgress, .m_deleteAllProgress): return .match - - case (.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let lhsBlocks, let lhsDownloadquality), .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let rhsBlocks, let rhsDownloadquality)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadquality, rhs: rhsDownloadquality, with: matcher), lhsDownloadquality, rhsDownloadquality, "downloadQuality")) - return Matcher.ComparisonResult(results) - - case (.m_updateTask__task_task(let lhsTask), .m_updateTask__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_downloadDataTask__for_blockId(let lhsBlockid), .m_downloadDataTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadDataTasks, .m_getDownloadDataTasks): return .match - - case (.m_getDownloadDataTasksForCourse__courseId(let lhsCourseid), .m_getDownloadDataTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_deleteDownloadDataTasks__ids_ids(let lhsIds), .m_deleteDownloadDataTasks__ids_ids(let rhsIds)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIds, rhs: rhsIds, with: matcher), lhsIds, rhsIds, "ids")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_set__userId_userId(p0): return p0.intValue - case .m_getUserID: return 0 - case .m_publisher: return 0 - case let .m_addToDownloadQueue__tasks_tasks(p0): return p0.intValue - case let .m_saveOfflineProgress__progress_progress(p0): return p0.intValue - case let .m_loadProgress__for_blockID(p0): return p0.intValue - case .m_loadAllOfflineProgress: return 0 - case let .m_deleteProgress__for_blockID(p0): return p0.intValue - case .m_deleteAllProgress: return 0 - case let .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(p0, p1): return p0.intValue + p1.intValue - case let .m_updateTask__task_task(p0): return p0.intValue - case let .m_downloadDataTask__for_blockId(p0): return p0.intValue - case .m_getDownloadDataTasks: return 0 - case let .m_getDownloadDataTasksForCourse__courseId(p0): return p0.intValue - case let .m_deleteDownloadDataTasks__ids_ids(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_set__userId_userId: return ".set(userId:)" - case .m_getUserID: return ".getUserID()" - case .m_publisher: return ".publisher()" - case .m_addToDownloadQueue__tasks_tasks: return ".addToDownloadQueue(tasks:)" - case .m_saveOfflineProgress__progress_progress: return ".saveOfflineProgress(progress:)" - case .m_loadProgress__for_blockID: return ".loadProgress(for:)" - case .m_loadAllOfflineProgress: return ".loadAllOfflineProgress()" - case .m_deleteProgress__for_blockID: return ".deleteProgress(for:)" - case .m_deleteAllProgress: return ".deleteAllProgress()" - case .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality: return ".addToDownloadQueue(blocks:downloadQuality:)" - case .m_updateTask__task_task: return ".updateTask(task:)" - case .m_downloadDataTask__for_blockId: return ".downloadDataTask(for:)" - case .m_getDownloadDataTasks: return ".getDownloadDataTasks()" - case .m_getDownloadDataTasksForCourse__courseId: return ".getDownloadDataTasksForCourse(_:)" - case .m_deleteDownloadDataTasks__ids_ids: return ".deleteDownloadDataTasks(ids:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getUserID(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @MainActor - public static func publisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_publisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadProgress(for blockID: Parameter, willReturn: OfflineProgress?...) -> MethodStub { - return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadAllOfflineProgress(willReturn: [OfflineProgress]...) -> MethodStub { - return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadDataTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getUserID(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func loadProgress(for blockID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [OfflineProgress?] = [] - let given: Given = { return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (OfflineProgress?).self) - willProduce(stubber) - return given - } - public static func loadAllOfflineProgress(willProduce: (Stubber<[OfflineProgress]>) -> Void) -> MethodStub { - let willReturn: [[OfflineProgress]] = [] - let given: Given = { return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([OfflineProgress]).self) - willProduce(stubber) - return given - } - public static func downloadDataTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - @MainActor - public static func publisher(willThrow: Error...) -> MethodStub { - return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) - } - @MainActor - public static func publisher(willProduce: (StubberThrows>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func set(userId: Parameter) -> Verify { return Verify(method: .m_set__userId_userId(`userId`))} - public static func getUserID() -> Verify { return Verify(method: .m_getUserID)} - @MainActor - public static func publisher() -> Verify { return Verify(method: .m_publisher)} - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>) -> Verify { return Verify(method: .m_addToDownloadQueue__tasks_tasks(`tasks`))} - public static func saveOfflineProgress(progress: Parameter) -> Verify { return Verify(method: .m_saveOfflineProgress__progress_progress(`progress`))} - public static func loadProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_loadProgress__for_blockID(`blockID`))} - public static func loadAllOfflineProgress() -> Verify { return Verify(method: .m_loadAllOfflineProgress)} - public static func deleteProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_deleteProgress__for_blockID(`blockID`))} - public static func deleteAllProgress() -> Verify { return Verify(method: .m_deleteAllProgress)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`))} - public static func updateTask(task: Parameter) -> Verify { return Verify(method: .m_updateTask__task_task(`task`))} - public static func downloadDataTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadDataTask__for_blockId(`blockId`))} - public static func getDownloadDataTasks() -> Verify { return Verify(method: .m_getDownloadDataTasks)} - public static func getDownloadDataTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`))} - public static func deleteDownloadDataTasks(ids: Parameter<[String]>) -> Verify { return Verify(method: .m_deleteDownloadDataTasks__ids_ids(`ids`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func set(userId: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_set__userId_userId(`userId`), performs: perform) - } - public static func getUserID(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getUserID, performs: perform) - } - @MainActor - public static func publisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_publisher, performs: perform) - } - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>, perform: @escaping ([DownloadDataTask]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__tasks_tasks(`tasks`), performs: perform) - } - public static func saveOfflineProgress(progress: Parameter, perform: @escaping (OfflineProgress) -> Void) -> Perform { - return Perform(method: .m_saveOfflineProgress__progress_progress(`progress`), performs: perform) - } - public static func loadProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_loadProgress__for_blockID(`blockID`), performs: perform) - } - public static func loadAllOfflineProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_loadAllOfflineProgress, performs: perform) - } - public static func deleteProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_deleteProgress__for_blockID(`blockID`), performs: perform) - } - public static func deleteAllProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAllProgress, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter, perform: @escaping ([CourseBlock], DownloadQuality) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`), performs: perform) - } - public static func updateTask(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_updateTask__task_task(`task`), performs: perform) - } - public static func downloadDataTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadDataTask__for_blockId(`blockId`), performs: perform) - } - public static func getDownloadDataTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasks, performs: perform) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func deleteDownloadDataTasks(ids: Parameter<[String]>, perform: @escaping ([String]) -> Void) -> Perform { - return Perform(method: .m_deleteDownloadDataTasks__ids_ids(`ids`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreStorage - -open class CoreStorageMock: CoreStorage, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var accessToken: String? { - get { invocations.append(.p_accessToken_get); return __p_accessToken ?? optionalGivenGetterValue(.p_accessToken_get, "CoreStorageMock - stub value for accessToken was not defined") } - set { invocations.append(.p_accessToken_set(.value(newValue))); __p_accessToken = newValue } - } - private var __p_accessToken: (String)? - - public var refreshToken: String? { - get { invocations.append(.p_refreshToken_get); return __p_refreshToken ?? optionalGivenGetterValue(.p_refreshToken_get, "CoreStorageMock - stub value for refreshToken was not defined") } - set { invocations.append(.p_refreshToken_set(.value(newValue))); __p_refreshToken = newValue } - } - private var __p_refreshToken: (String)? - - public var pushToken: String? { - get { invocations.append(.p_pushToken_get); return __p_pushToken ?? optionalGivenGetterValue(.p_pushToken_get, "CoreStorageMock - stub value for pushToken was not defined") } - set { invocations.append(.p_pushToken_set(.value(newValue))); __p_pushToken = newValue } - } - private var __p_pushToken: (String)? - - public var appleSignFullName: String? { - get { invocations.append(.p_appleSignFullName_get); return __p_appleSignFullName ?? optionalGivenGetterValue(.p_appleSignFullName_get, "CoreStorageMock - stub value for appleSignFullName was not defined") } - set { invocations.append(.p_appleSignFullName_set(.value(newValue))); __p_appleSignFullName = newValue } - } - private var __p_appleSignFullName: (String)? - - public var appleSignEmail: String? { - get { invocations.append(.p_appleSignEmail_get); return __p_appleSignEmail ?? optionalGivenGetterValue(.p_appleSignEmail_get, "CoreStorageMock - stub value for appleSignEmail was not defined") } - set { invocations.append(.p_appleSignEmail_set(.value(newValue))); __p_appleSignEmail = newValue } - } - private var __p_appleSignEmail: (String)? - - public var cookiesDate: Date? { - get { invocations.append(.p_cookiesDate_get); return __p_cookiesDate ?? optionalGivenGetterValue(.p_cookiesDate_get, "CoreStorageMock - stub value for cookiesDate was not defined") } - set { invocations.append(.p_cookiesDate_set(.value(newValue))); __p_cookiesDate = newValue } - } - private var __p_cookiesDate: (Date)? - - public var reviewLastShownVersion: String? { - get { invocations.append(.p_reviewLastShownVersion_get); return __p_reviewLastShownVersion ?? optionalGivenGetterValue(.p_reviewLastShownVersion_get, "CoreStorageMock - stub value for reviewLastShownVersion was not defined") } - set { invocations.append(.p_reviewLastShownVersion_set(.value(newValue))); __p_reviewLastShownVersion = newValue } - } - private var __p_reviewLastShownVersion: (String)? - - public var lastReviewDate: Date? { - get { invocations.append(.p_lastReviewDate_get); return __p_lastReviewDate ?? optionalGivenGetterValue(.p_lastReviewDate_get, "CoreStorageMock - stub value for lastReviewDate was not defined") } - set { invocations.append(.p_lastReviewDate_set(.value(newValue))); __p_lastReviewDate = newValue } - } - private var __p_lastReviewDate: (Date)? - - public var user: DataLayer.User? { - get { invocations.append(.p_user_get); return __p_user ?? optionalGivenGetterValue(.p_user_get, "CoreStorageMock - stub value for user was not defined") } - set { invocations.append(.p_user_set(.value(newValue))); __p_user = newValue } - } - private var __p_user: (DataLayer.User)? - - public var userSettings: UserSettings? { - get { invocations.append(.p_userSettings_get); return __p_userSettings ?? optionalGivenGetterValue(.p_userSettings_get, "CoreStorageMock - stub value for userSettings was not defined") } - set { invocations.append(.p_userSettings_set(.value(newValue))); __p_userSettings = newValue } - } - private var __p_userSettings: (UserSettings)? - - public var resetAppSupportDirectoryUserData: Bool? { - get { invocations.append(.p_resetAppSupportDirectoryUserData_get); return __p_resetAppSupportDirectoryUserData ?? optionalGivenGetterValue(.p_resetAppSupportDirectoryUserData_get, "CoreStorageMock - stub value for resetAppSupportDirectoryUserData was not defined") } - set { invocations.append(.p_resetAppSupportDirectoryUserData_set(.value(newValue))); __p_resetAppSupportDirectoryUserData = newValue } - } - private var __p_resetAppSupportDirectoryUserData: (Bool)? - - public var useRelativeDates: Bool { - get { invocations.append(.p_useRelativeDates_get); return __p_useRelativeDates ?? givenGetterValue(.p_useRelativeDates_get, "CoreStorageMock - stub value for useRelativeDates was not defined") } - set { invocations.append(.p_useRelativeDates_set(.value(newValue))); __p_useRelativeDates = newValue } - } - private var __p_useRelativeDates: (Bool)? - - public var lastUsedSocialAuth: String? { - get { invocations.append(.p_lastUsedSocialAuth_get); return __p_lastUsedSocialAuth ?? optionalGivenGetterValue(.p_lastUsedSocialAuth_get, "CoreStorageMock - stub value for lastUsedSocialAuth was not defined") } - set { invocations.append(.p_lastUsedSocialAuth_set(.value(newValue))); __p_lastUsedSocialAuth = newValue } - } - private var __p_lastUsedSocialAuth: (String)? - - public var latestAvailableAppVersion: String? { - get { invocations.append(.p_latestAvailableAppVersion_get); return __p_latestAvailableAppVersion ?? optionalGivenGetterValue(.p_latestAvailableAppVersion_get, "CoreStorageMock - stub value for latestAvailableAppVersion was not defined") } - set { invocations.append(.p_latestAvailableAppVersion_set(.value(newValue))); __p_latestAvailableAppVersion = newValue } - } - private var __p_latestAvailableAppVersion: (String)? - - public var updateAppRequired: Bool { - get { invocations.append(.p_updateAppRequired_get); return __p_updateAppRequired ?? givenGetterValue(.p_updateAppRequired_get, "CoreStorageMock - stub value for updateAppRequired was not defined") } - set { invocations.append(.p_updateAppRequired_set(.value(newValue))); __p_updateAppRequired = newValue } - } - private var __p_updateAppRequired: (Bool)? - - - - - - open func clear() { - addInvocation(.m_clear) - let perform = methodPerformValue(.m_clear) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_clear - case p_accessToken_get - case p_accessToken_set(Parameter) - case p_refreshToken_get - case p_refreshToken_set(Parameter) - case p_pushToken_get - case p_pushToken_set(Parameter) - case p_appleSignFullName_get - case p_appleSignFullName_set(Parameter) - case p_appleSignEmail_get - case p_appleSignEmail_set(Parameter) - case p_cookiesDate_get - case p_cookiesDate_set(Parameter) - case p_reviewLastShownVersion_get - case p_reviewLastShownVersion_set(Parameter) - case p_lastReviewDate_get - case p_lastReviewDate_set(Parameter) - case p_user_get - case p_user_set(Parameter) - case p_userSettings_get - case p_userSettings_set(Parameter) - case p_resetAppSupportDirectoryUserData_get - case p_resetAppSupportDirectoryUserData_set(Parameter) - case p_useRelativeDates_get - case p_useRelativeDates_set(Parameter) - case p_lastUsedSocialAuth_get - case p_lastUsedSocialAuth_set(Parameter) - case p_latestAvailableAppVersion_get - case p_latestAvailableAppVersion_set(Parameter) - case p_updateAppRequired_get - case p_updateAppRequired_set(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_clear, .m_clear): return .match - case (.p_accessToken_get,.p_accessToken_get): return Matcher.ComparisonResult.match - case (.p_accessToken_set(let left),.p_accessToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_refreshToken_get,.p_refreshToken_get): return Matcher.ComparisonResult.match - case (.p_refreshToken_set(let left),.p_refreshToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_pushToken_get,.p_pushToken_get): return Matcher.ComparisonResult.match - case (.p_pushToken_set(let left),.p_pushToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignFullName_get,.p_appleSignFullName_get): return Matcher.ComparisonResult.match - case (.p_appleSignFullName_set(let left),.p_appleSignFullName_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignEmail_get,.p_appleSignEmail_get): return Matcher.ComparisonResult.match - case (.p_appleSignEmail_set(let left),.p_appleSignEmail_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_cookiesDate_get,.p_cookiesDate_get): return Matcher.ComparisonResult.match - case (.p_cookiesDate_set(let left),.p_cookiesDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_reviewLastShownVersion_get,.p_reviewLastShownVersion_get): return Matcher.ComparisonResult.match - case (.p_reviewLastShownVersion_set(let left),.p_reviewLastShownVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastReviewDate_get,.p_lastReviewDate_get): return Matcher.ComparisonResult.match - case (.p_lastReviewDate_set(let left),.p_lastReviewDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_user_get,.p_user_get): return Matcher.ComparisonResult.match - case (.p_user_set(let left),.p_user_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_userSettings_get,.p_userSettings_get): return Matcher.ComparisonResult.match - case (.p_userSettings_set(let left),.p_userSettings_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_resetAppSupportDirectoryUserData_get,.p_resetAppSupportDirectoryUserData_get): return Matcher.ComparisonResult.match - case (.p_resetAppSupportDirectoryUserData_set(let left),.p_resetAppSupportDirectoryUserData_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_useRelativeDates_get,.p_useRelativeDates_get): return Matcher.ComparisonResult.match - case (.p_useRelativeDates_set(let left),.p_useRelativeDates_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastUsedSocialAuth_get,.p_lastUsedSocialAuth_get): return Matcher.ComparisonResult.match - case (.p_lastUsedSocialAuth_set(let left),.p_lastUsedSocialAuth_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_latestAvailableAppVersion_get,.p_latestAvailableAppVersion_get): return Matcher.ComparisonResult.match - case (.p_latestAvailableAppVersion_set(let left),.p_latestAvailableAppVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_updateAppRequired_get,.p_updateAppRequired_get): return Matcher.ComparisonResult.match - case (.p_updateAppRequired_set(let left),.p_updateAppRequired_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_clear: return 0 - case .p_accessToken_get: return 0 - case .p_accessToken_set(let newValue): return newValue.intValue - case .p_refreshToken_get: return 0 - case .p_refreshToken_set(let newValue): return newValue.intValue - case .p_pushToken_get: return 0 - case .p_pushToken_set(let newValue): return newValue.intValue - case .p_appleSignFullName_get: return 0 - case .p_appleSignFullName_set(let newValue): return newValue.intValue - case .p_appleSignEmail_get: return 0 - case .p_appleSignEmail_set(let newValue): return newValue.intValue - case .p_cookiesDate_get: return 0 - case .p_cookiesDate_set(let newValue): return newValue.intValue - case .p_reviewLastShownVersion_get: return 0 - case .p_reviewLastShownVersion_set(let newValue): return newValue.intValue - case .p_lastReviewDate_get: return 0 - case .p_lastReviewDate_set(let newValue): return newValue.intValue - case .p_user_get: return 0 - case .p_user_set(let newValue): return newValue.intValue - case .p_userSettings_get: return 0 - case .p_userSettings_set(let newValue): return newValue.intValue - case .p_resetAppSupportDirectoryUserData_get: return 0 - case .p_resetAppSupportDirectoryUserData_set(let newValue): return newValue.intValue - case .p_useRelativeDates_get: return 0 - case .p_useRelativeDates_set(let newValue): return newValue.intValue - case .p_lastUsedSocialAuth_get: return 0 - case .p_lastUsedSocialAuth_set(let newValue): return newValue.intValue - case .p_latestAvailableAppVersion_get: return 0 - case .p_latestAvailableAppVersion_set(let newValue): return newValue.intValue - case .p_updateAppRequired_get: return 0 - case .p_updateAppRequired_set(let newValue): return newValue.intValue - } - } - func assertionName() -> String { - switch self { - case .m_clear: return ".clear()" - case .p_accessToken_get: return "[get] .accessToken" - case .p_accessToken_set: return "[set] .accessToken" - case .p_refreshToken_get: return "[get] .refreshToken" - case .p_refreshToken_set: return "[set] .refreshToken" - case .p_pushToken_get: return "[get] .pushToken" - case .p_pushToken_set: return "[set] .pushToken" - case .p_appleSignFullName_get: return "[get] .appleSignFullName" - case .p_appleSignFullName_set: return "[set] .appleSignFullName" - case .p_appleSignEmail_get: return "[get] .appleSignEmail" - case .p_appleSignEmail_set: return "[set] .appleSignEmail" - case .p_cookiesDate_get: return "[get] .cookiesDate" - case .p_cookiesDate_set: return "[set] .cookiesDate" - case .p_reviewLastShownVersion_get: return "[get] .reviewLastShownVersion" - case .p_reviewLastShownVersion_set: return "[set] .reviewLastShownVersion" - case .p_lastReviewDate_get: return "[get] .lastReviewDate" - case .p_lastReviewDate_set: return "[set] .lastReviewDate" - case .p_user_get: return "[get] .user" - case .p_user_set: return "[set] .user" - case .p_userSettings_get: return "[get] .userSettings" - case .p_userSettings_set: return "[set] .userSettings" - case .p_resetAppSupportDirectoryUserData_get: return "[get] .resetAppSupportDirectoryUserData" - case .p_resetAppSupportDirectoryUserData_set: return "[set] .resetAppSupportDirectoryUserData" - case .p_useRelativeDates_get: return "[get] .useRelativeDates" - case .p_useRelativeDates_set: return "[set] .useRelativeDates" - case .p_lastUsedSocialAuth_get: return "[get] .lastUsedSocialAuth" - case .p_lastUsedSocialAuth_set: return "[set] .lastUsedSocialAuth" - case .p_latestAvailableAppVersion_get: return "[get] .latestAvailableAppVersion" - case .p_latestAvailableAppVersion_set: return "[set] .latestAvailableAppVersion" - case .p_updateAppRequired_get: return "[get] .updateAppRequired" - case .p_updateAppRequired_set: return "[set] .updateAppRequired" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func accessToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_accessToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func refreshToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_refreshToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func pushToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_pushToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignFullName(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignFullName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignEmail(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func cookiesDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_cookiesDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func reviewLastShownVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_reviewLastShownVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastReviewDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_lastReviewDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func user(getter defaultValue: DataLayer.User?...) -> PropertyStub { - return Given(method: .p_user_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func userSettings(getter defaultValue: UserSettings?...) -> PropertyStub { - return Given(method: .p_userSettings_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func resetAppSupportDirectoryUserData(getter defaultValue: Bool?...) -> PropertyStub { - return Given(method: .p_resetAppSupportDirectoryUserData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func useRelativeDates(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_useRelativeDates_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastUsedSocialAuth(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_lastUsedSocialAuth_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func latestAvailableAppVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_latestAvailableAppVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func updateAppRequired(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_updateAppRequired_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func clear() -> Verify { return Verify(method: .m_clear)} - public static var accessToken: Verify { return Verify(method: .p_accessToken_get) } - public static func accessToken(set newValue: Parameter) -> Verify { return Verify(method: .p_accessToken_set(newValue)) } - public static var refreshToken: Verify { return Verify(method: .p_refreshToken_get) } - public static func refreshToken(set newValue: Parameter) -> Verify { return Verify(method: .p_refreshToken_set(newValue)) } - public static var pushToken: Verify { return Verify(method: .p_pushToken_get) } - public static func pushToken(set newValue: Parameter) -> Verify { return Verify(method: .p_pushToken_set(newValue)) } - public static var appleSignFullName: Verify { return Verify(method: .p_appleSignFullName_get) } - public static func appleSignFullName(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignFullName_set(newValue)) } - public static var appleSignEmail: Verify { return Verify(method: .p_appleSignEmail_get) } - public static func appleSignEmail(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignEmail_set(newValue)) } - public static var cookiesDate: Verify { return Verify(method: .p_cookiesDate_get) } - public static func cookiesDate(set newValue: Parameter) -> Verify { return Verify(method: .p_cookiesDate_set(newValue)) } - public static var reviewLastShownVersion: Verify { return Verify(method: .p_reviewLastShownVersion_get) } - public static func reviewLastShownVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_reviewLastShownVersion_set(newValue)) } - public static var lastReviewDate: Verify { return Verify(method: .p_lastReviewDate_get) } - public static func lastReviewDate(set newValue: Parameter) -> Verify { return Verify(method: .p_lastReviewDate_set(newValue)) } - public static var user: Verify { return Verify(method: .p_user_get) } - public static func user(set newValue: Parameter) -> Verify { return Verify(method: .p_user_set(newValue)) } - public static var userSettings: Verify { return Verify(method: .p_userSettings_get) } - public static func userSettings(set newValue: Parameter) -> Verify { return Verify(method: .p_userSettings_set(newValue)) } - public static var resetAppSupportDirectoryUserData: Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_get) } - public static func resetAppSupportDirectoryUserData(set newValue: Parameter) -> Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_set(newValue)) } - public static var useRelativeDates: Verify { return Verify(method: .p_useRelativeDates_get) } - public static func useRelativeDates(set newValue: Parameter) -> Verify { return Verify(method: .p_useRelativeDates_set(newValue)) } - public static var lastUsedSocialAuth: Verify { return Verify(method: .p_lastUsedSocialAuth_get) } - public static func lastUsedSocialAuth(set newValue: Parameter) -> Verify { return Verify(method: .p_lastUsedSocialAuth_set(newValue)) } - public static var latestAvailableAppVersion: Verify { return Verify(method: .p_latestAvailableAppVersion_get) } - public static func latestAvailableAppVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_latestAvailableAppVersion_set(newValue)) } - public static var updateAppRequired: Verify { return Verify(method: .p_updateAppRequired_get) } - public static func updateAppRequired(set newValue: Parameter) -> Verify { return Verify(method: .p_updateAppRequired_set(newValue)) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func clear(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_clear, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CourseStructureManagerProtocol - -open class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getLoadedCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func shiftDueDates(courseID: String) throws { - addInvocation(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - do { - _ = try methodReturnValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - - fileprivate enum MethodType { - case m_getCourseBlocks__courseID_courseID(Parameter) - case m_getLoadedCourseBlocks__courseID_courseID(Parameter) - case m_shiftDueDates__courseID_courseID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseBlocks__courseID_courseID(let lhsCourseid), .m_getCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getLoadedCourseBlocks__courseID_courseID(let lhsCourseid), .m_getLoadedCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_shiftDueDates__courseID_courseID(let lhsCourseid), .m_shiftDueDates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_getLoadedCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_shiftDueDates__courseID_courseID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getCourseBlocks__courseID_courseID: return ".getCourseBlocks(courseID:)" - case .m_getLoadedCourseBlocks__courseID_courseID: return ".getLoadedCourseBlocks(courseID:)" - case .m_shiftDueDates__courseID_courseID: return ".shiftDueDates(courseID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getLoadedCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func shiftDueDates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func shiftDueDates(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseBlocks__courseID_courseID(`courseID`))} - public static func getLoadedCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`))} - public static func shiftDueDates(courseID: Parameter) -> Verify { return Verify(method: .m_shiftDueDates__courseID_courseID(`courseID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func getLoadedCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func shiftDueDates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_shiftDueDates__courseID_courseID(`courseID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DashboardAnalytics - -open class DashboardAnalyticsMock: DashboardAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func dashboardCourseClicked(courseID: String, courseName: String) { - addInvocation(.m_dashboardCourseClicked__courseID_courseIDcourseName_courseName(Parameter.value(`courseID`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_dashboardCourseClicked__courseID_courseIDcourseName_courseName(Parameter.value(`courseID`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseID`, `courseName`) - } - - open func mainProgramsClicked() { - addInvocation(.m_mainProgramsClicked) - let perform = methodPerformValue(.m_mainProgramsClicked) as? () -> Void - perform?() - } - - open func mainCoursesClicked() { - addInvocation(.m_mainCoursesClicked) - let perform = methodPerformValue(.m_mainCoursesClicked) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_dashboardCourseClicked__courseID_courseIDcourseName_courseName(Parameter, Parameter) - case m_mainProgramsClicked - case m_mainCoursesClicked - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_dashboardCourseClicked__courseID_courseIDcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_dashboardCourseClicked__courseID_courseIDcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_mainProgramsClicked, .m_mainProgramsClicked): return .match - - case (.m_mainCoursesClicked, .m_mainCoursesClicked): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_dashboardCourseClicked__courseID_courseIDcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case .m_mainProgramsClicked: return 0 - case .m_mainCoursesClicked: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_dashboardCourseClicked__courseID_courseIDcourseName_courseName: return ".dashboardCourseClicked(courseID:courseName:)" - case .m_mainProgramsClicked: return ".mainProgramsClicked()" - case .m_mainCoursesClicked: return ".mainCoursesClicked()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func dashboardCourseClicked(courseID: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_dashboardCourseClicked__courseID_courseIDcourseName_courseName(`courseID`, `courseName`))} - public static func mainProgramsClicked() -> Verify { return Verify(method: .m_mainProgramsClicked)} - public static func mainCoursesClicked() -> Verify { return Verify(method: .m_mainCoursesClicked)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func dashboardCourseClicked(courseID: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_dashboardCourseClicked__courseID_courseIDcourseName_courseName(`courseID`, `courseName`), performs: perform) - } - public static func mainProgramsClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_mainProgramsClicked, performs: perform) - } - public static func mainCoursesClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_mainCoursesClicked, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DashboardInteractorProtocol - -open class DashboardInteractorProtocolMock: DashboardInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getEnrollments(page: Int) throws -> [CourseItem] { - addInvocation(.m_getEnrollments__page_page(Parameter.value(`page`))) - let perform = methodPerformValue(.m_getEnrollments__page_page(Parameter.value(`page`))) as? (Int) -> Void - perform?(`page`) - var __value: [CourseItem] - do { - __value = try methodReturnValue(.m_getEnrollments__page_page(Parameter.value(`page`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getEnrollments(page: Int). Use given") - Failure("Stub return value not specified for getEnrollments(page: Int). Use given") - } catch { - throw error - } - return __value - } - - open func getEnrollmentsOffline() throws -> [CourseItem] { - addInvocation(.m_getEnrollmentsOffline) - let perform = methodPerformValue(.m_getEnrollmentsOffline) as? () -> Void - perform?() - var __value: [CourseItem] - do { - __value = try methodReturnValue(.m_getEnrollmentsOffline).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getEnrollmentsOffline(). Use given") - Failure("Stub return value not specified for getEnrollmentsOffline(). Use given") - } catch { - throw error - } - return __value - } - - open func getPrimaryEnrollment(pageSize: Int) throws -> PrimaryEnrollment { - addInvocation(.m_getPrimaryEnrollment__pageSize_pageSize(Parameter.value(`pageSize`))) - let perform = methodPerformValue(.m_getPrimaryEnrollment__pageSize_pageSize(Parameter.value(`pageSize`))) as? (Int) -> Void - perform?(`pageSize`) - var __value: PrimaryEnrollment - do { - __value = try methodReturnValue(.m_getPrimaryEnrollment__pageSize_pageSize(Parameter.value(`pageSize`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getPrimaryEnrollment(pageSize: Int). Use given") - Failure("Stub return value not specified for getPrimaryEnrollment(pageSize: Int). Use given") - } catch { - throw error - } - return __value - } - - open func getPrimaryEnrollmentOffline() throws -> PrimaryEnrollment { - addInvocation(.m_getPrimaryEnrollmentOffline) - let perform = methodPerformValue(.m_getPrimaryEnrollmentOffline) as? () -> Void - perform?() - var __value: PrimaryEnrollment - do { - __value = try methodReturnValue(.m_getPrimaryEnrollmentOffline).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getPrimaryEnrollmentOffline(). Use given") - Failure("Stub return value not specified for getPrimaryEnrollmentOffline(). Use given") - } catch { - throw error - } - return __value - } - - open func getAllCourses(filteredBy: String, page: Int) throws -> PrimaryEnrollment { - addInvocation(.m_getAllCourses__filteredBy_filteredBypage_page(Parameter.value(`filteredBy`), Parameter.value(`page`))) - let perform = methodPerformValue(.m_getAllCourses__filteredBy_filteredBypage_page(Parameter.value(`filteredBy`), Parameter.value(`page`))) as? (String, Int) -> Void - perform?(`filteredBy`, `page`) - var __value: PrimaryEnrollment - do { - __value = try methodReturnValue(.m_getAllCourses__filteredBy_filteredBypage_page(Parameter.value(`filteredBy`), Parameter.value(`page`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getAllCourses(filteredBy: String, page: Int). Use given") - Failure("Stub return value not specified for getAllCourses(filteredBy: String, page: Int). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_getEnrollments__page_page(Parameter) - case m_getEnrollmentsOffline - case m_getPrimaryEnrollment__pageSize_pageSize(Parameter) - case m_getPrimaryEnrollmentOffline - case m_getAllCourses__filteredBy_filteredBypage_page(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getEnrollments__page_page(let lhsPage), .m_getEnrollments__page_page(let rhsPage)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPage, rhs: rhsPage, with: matcher), lhsPage, rhsPage, "page")) - return Matcher.ComparisonResult(results) - - case (.m_getEnrollmentsOffline, .m_getEnrollmentsOffline): return .match - - case (.m_getPrimaryEnrollment__pageSize_pageSize(let lhsPagesize), .m_getPrimaryEnrollment__pageSize_pageSize(let rhsPagesize)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPagesize, rhs: rhsPagesize, with: matcher), lhsPagesize, rhsPagesize, "pageSize")) - return Matcher.ComparisonResult(results) - - case (.m_getPrimaryEnrollmentOffline, .m_getPrimaryEnrollmentOffline): return .match - - case (.m_getAllCourses__filteredBy_filteredBypage_page(let lhsFilteredby, let lhsPage), .m_getAllCourses__filteredBy_filteredBypage_page(let rhsFilteredby, let rhsPage)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFilteredby, rhs: rhsFilteredby, with: matcher), lhsFilteredby, rhsFilteredby, "filteredBy")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPage, rhs: rhsPage, with: matcher), lhsPage, rhsPage, "page")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getEnrollments__page_page(p0): return p0.intValue - case .m_getEnrollmentsOffline: return 0 - case let .m_getPrimaryEnrollment__pageSize_pageSize(p0): return p0.intValue - case .m_getPrimaryEnrollmentOffline: return 0 - case let .m_getAllCourses__filteredBy_filteredBypage_page(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getEnrollments__page_page: return ".getEnrollments(page:)" - case .m_getEnrollmentsOffline: return ".getEnrollmentsOffline()" - case .m_getPrimaryEnrollment__pageSize_pageSize: return ".getPrimaryEnrollment(pageSize:)" - case .m_getPrimaryEnrollmentOffline: return ".getPrimaryEnrollmentOffline()" - case .m_getAllCourses__filteredBy_filteredBypage_page: return ".getAllCourses(filteredBy:page:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getEnrollments(page: Parameter, willReturn: [CourseItem]...) -> MethodStub { - return Given(method: .m_getEnrollments__page_page(`page`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getEnrollmentsOffline(willReturn: [CourseItem]...) -> MethodStub { - return Given(method: .m_getEnrollmentsOffline, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getPrimaryEnrollment(pageSize: Parameter, willReturn: PrimaryEnrollment...) -> MethodStub { - return Given(method: .m_getPrimaryEnrollment__pageSize_pageSize(`pageSize`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getPrimaryEnrollmentOffline(willReturn: PrimaryEnrollment...) -> MethodStub { - return Given(method: .m_getPrimaryEnrollmentOffline, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getAllCourses(filteredBy: Parameter, page: Parameter, willReturn: PrimaryEnrollment...) -> MethodStub { - return Given(method: .m_getAllCourses__filteredBy_filteredBypage_page(`filteredBy`, `page`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getEnrollments(page: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getEnrollments__page_page(`page`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getEnrollments(page: Parameter, willProduce: (StubberThrows<[CourseItem]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getEnrollments__page_page(`page`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([CourseItem]).self) - willProduce(stubber) - return given - } - public static func getEnrollmentsOffline(willThrow: Error...) -> MethodStub { - return Given(method: .m_getEnrollmentsOffline, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getEnrollmentsOffline(willProduce: (StubberThrows<[CourseItem]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getEnrollmentsOffline, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([CourseItem]).self) - willProduce(stubber) - return given - } - public static func getPrimaryEnrollment(pageSize: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getPrimaryEnrollment__pageSize_pageSize(`pageSize`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getPrimaryEnrollment(pageSize: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getPrimaryEnrollment__pageSize_pageSize(`pageSize`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (PrimaryEnrollment).self) - willProduce(stubber) - return given - } - public static func getPrimaryEnrollmentOffline(willThrow: Error...) -> MethodStub { - return Given(method: .m_getPrimaryEnrollmentOffline, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getPrimaryEnrollmentOffline(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getPrimaryEnrollmentOffline, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (PrimaryEnrollment).self) - willProduce(stubber) - return given - } - public static func getAllCourses(filteredBy: Parameter, page: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getAllCourses__filteredBy_filteredBypage_page(`filteredBy`, `page`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getAllCourses(filteredBy: Parameter, page: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getAllCourses__filteredBy_filteredBypage_page(`filteredBy`, `page`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (PrimaryEnrollment).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getEnrollments(page: Parameter) -> Verify { return Verify(method: .m_getEnrollments__page_page(`page`))} - public static func getEnrollmentsOffline() -> Verify { return Verify(method: .m_getEnrollmentsOffline)} - public static func getPrimaryEnrollment(pageSize: Parameter) -> Verify { return Verify(method: .m_getPrimaryEnrollment__pageSize_pageSize(`pageSize`))} - public static func getPrimaryEnrollmentOffline() -> Verify { return Verify(method: .m_getPrimaryEnrollmentOffline)} - public static func getAllCourses(filteredBy: Parameter, page: Parameter) -> Verify { return Verify(method: .m_getAllCourses__filteredBy_filteredBypage_page(`filteredBy`, `page`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getEnrollments(page: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_getEnrollments__page_page(`page`), performs: perform) - } - public static func getEnrollmentsOffline(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getEnrollmentsOffline, performs: perform) - } - public static func getPrimaryEnrollment(pageSize: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_getPrimaryEnrollment__pageSize_pageSize(`pageSize`), performs: perform) - } - public static func getPrimaryEnrollmentOffline(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getPrimaryEnrollmentOffline, performs: perform) - } - public static func getAllCourses(filteredBy: Parameter, page: Parameter, perform: @escaping (String, Int) -> Void) -> Perform { - return Perform(method: .m_getAllCourses__filteredBy_filteredBypage_page(`filteredBy`, `page`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DownloadManagerProtocol - -open class DownloadManagerProtocolMock: DownloadManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCurrentDownloadTask() -> DownloadDataTask? { - addInvocation(.m_getCurrentDownloadTask) - let perform = methodPerformValue(.m_getCurrentDownloadTask) as? () -> Void - perform?() - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_getCurrentDownloadTask).casted() - } catch { - // do nothing - } - return __value - } - - open func eventPublisher() -> AnyPublisher { - addInvocation(.m_eventPublisher) - let perform = methodPerformValue(.m_eventPublisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_eventPublisher).casted() - } catch { - onFatalFailure("Stub return value not specified for eventPublisher(). Use given") - Failure("Stub return value not specified for eventPublisher(). Use given") - } - return __value - } - - open func addToDownloadQueue(blocks: [CourseBlock]) throws { - addInvocation(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - do { - _ = try methodReturnValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getDownloadTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasks) - let perform = methodPerformValue(.m_getDownloadTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasks(). Use given") - Failure("Stub return value not specified for getDownloadTasks(). Use given") - } - return __value - } - - open func getDownloadTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func cancelDownloading(courseId: String, blocks: [CourseBlock]) throws { - addInvocation(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) as? (String, [CourseBlock]) -> Void - perform?(`courseId`, `blocks`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(task: DownloadDataTask) throws { - addInvocation(.m_cancelDownloading__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_cancelDownloading__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - do { - _ = try methodReturnValue(.m_cancelDownloading__task_task(Parameter.value(`task`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(courseId: String) throws { - addInvocation(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelAllDownloading() throws { - addInvocation(.m_cancelAllDownloading) - let perform = methodPerformValue(.m_cancelAllDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_cancelAllDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func deleteAll() { - addInvocation(.m_deleteAll) - let perform = methodPerformValue(.m_deleteAll) as? () -> Void - perform?() - } - - open func fileUrl(for blockId: String) -> URL? { - addInvocation(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: URL? = nil - do { - __value = try methodReturnValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func resumeDownloading() throws { - addInvocation(.m_resumeDownloading) - let perform = methodPerformValue(.m_resumeDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_resumeDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func isLargeVideosSize(blocks: [CourseBlock]) -> Bool { - addInvocation(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - Failure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - } - return __value - } - - open func removeAppSupportDirectoryUnusedContent() { - addInvocation(.m_removeAppSupportDirectoryUnusedContent) - let perform = methodPerformValue(.m_removeAppSupportDirectoryUnusedContent) as? () -> Void - perform?() - } - - open func delete(blocks: [CourseBlock], courseId: String) { - addInvocation(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) as? ([CourseBlock], String) -> Void - perform?(`blocks`, `courseId`) - } - - open func downloadTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getFreeDiskSpace() -> Int? { - addInvocation(.m_getFreeDiskSpace) - let perform = methodPerformValue(.m_getFreeDiskSpace) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getFreeDiskSpace).casted() - } catch { - // do nothing - } - return __value - } - - - fileprivate enum MethodType { - case m_getCurrentDownloadTask - case m_eventPublisher - case m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>) - case m_getDownloadTasks - case m_getDownloadTasksForCourse__courseId(Parameter) - case m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter, Parameter<[CourseBlock]>) - case m_cancelDownloading__task_task(Parameter) - case m_cancelDownloading__courseId_courseId(Parameter) - case m_cancelAllDownloading - case m_deleteAll - case m_fileUrl__for_blockId(Parameter) - case m_resumeDownloading - case m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>) - case m_removeAppSupportDirectoryUnusedContent - case m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>, Parameter) - case m_downloadTask__for_blockId(Parameter) - case m_getFreeDiskSpace - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCurrentDownloadTask, .m_getCurrentDownloadTask): return .match - - case (.m_eventPublisher, .m_eventPublisher): return .match - - case (.m_addToDownloadQueue__blocks_blocks(let lhsBlocks), .m_addToDownloadQueue__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadTasks, .m_getDownloadTasks): return .match - - case (.m_getDownloadTasksForCourse__courseId(let lhsCourseid), .m_getDownloadTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseIdblocks_blocks(let lhsCourseid, let lhsBlocks), .m_cancelDownloading__courseId_courseIdblocks_blocks(let rhsCourseid, let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__task_task(let lhsTask), .m_cancelDownloading__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseId(let lhsCourseid), .m_cancelDownloading__courseId_courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelAllDownloading, .m_cancelAllDownloading): return .match - - case (.m_deleteAll, .m_deleteAll): return .match - - case (.m_fileUrl__for_blockId(let lhsBlockid), .m_fileUrl__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_resumeDownloading, .m_resumeDownloading): return .match - - case (.m_isLargeVideosSize__blocks_blocks(let lhsBlocks), .m_isLargeVideosSize__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_removeAppSupportDirectoryUnusedContent, .m_removeAppSupportDirectoryUnusedContent): return .match - - case (.m_delete__blocks_blockscourseId_courseId(let lhsBlocks, let lhsCourseid), .m_delete__blocks_blockscourseId_courseId(let rhsBlocks, let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_downloadTask__for_blockId(let lhsBlockid), .m_downloadTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getFreeDiskSpace, .m_getFreeDiskSpace): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_getCurrentDownloadTask: return 0 - case .m_eventPublisher: return 0 - case let .m_addToDownloadQueue__blocks_blocks(p0): return p0.intValue - case .m_getDownloadTasks: return 0 - case let .m_getDownloadTasksForCourse__courseId(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseIdblocks_blocks(p0, p1): return p0.intValue + p1.intValue - case let .m_cancelDownloading__task_task(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseId(p0): return p0.intValue - case .m_cancelAllDownloading: return 0 - case .m_deleteAll: return 0 - case let .m_fileUrl__for_blockId(p0): return p0.intValue - case .m_resumeDownloading: return 0 - case let .m_isLargeVideosSize__blocks_blocks(p0): return p0.intValue - case .m_removeAppSupportDirectoryUnusedContent: return 0 - case let .m_delete__blocks_blockscourseId_courseId(p0, p1): return p0.intValue + p1.intValue - case let .m_downloadTask__for_blockId(p0): return p0.intValue - case .m_getFreeDiskSpace: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_getCurrentDownloadTask: return ".getCurrentDownloadTask()" - case .m_eventPublisher: return ".eventPublisher()" - case .m_addToDownloadQueue__blocks_blocks: return ".addToDownloadQueue(blocks:)" - case .m_getDownloadTasks: return ".getDownloadTasks()" - case .m_getDownloadTasksForCourse__courseId: return ".getDownloadTasksForCourse(_:)" - case .m_cancelDownloading__courseId_courseIdblocks_blocks: return ".cancelDownloading(courseId:blocks:)" - case .m_cancelDownloading__task_task: return ".cancelDownloading(task:)" - case .m_cancelDownloading__courseId_courseId: return ".cancelDownloading(courseId:)" - case .m_cancelAllDownloading: return ".cancelAllDownloading()" - case .m_deleteAll: return ".deleteAll()" - case .m_fileUrl__for_blockId: return ".fileUrl(for:)" - case .m_resumeDownloading: return ".resumeDownloading()" - case .m_isLargeVideosSize__blocks_blocks: return ".isLargeVideosSize(blocks:)" - case .m_removeAppSupportDirectoryUnusedContent: return ".removeAppSupportDirectoryUnusedContent()" - case .m_delete__blocks_blockscourseId_courseId: return ".delete(blocks:courseId:)" - case .m_downloadTask__for_blockId: return ".downloadTask(for:)" - case .m_getFreeDiskSpace: return ".getFreeDiskSpace()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCurrentDownloadTask(willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func eventPublisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func fileUrl(for blockId: Parameter, willReturn: URL?...) -> MethodStub { - return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getFreeDiskSpace(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCurrentDownloadTask(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func eventPublisher(willProduce: (Stubber>) -> Void) -> MethodStub { - let willReturn: [AnyPublisher] = [] - let given: Given = { return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - public static func getDownloadTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func fileUrl(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [URL?] = [] - let given: Given = { return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (URL?).self) - willProduce(stubber) - return given - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func downloadTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getFreeDiskSpace(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(task: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(task: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelAllDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelAllDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func resumeDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resumeDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCurrentDownloadTask() -> Verify { return Verify(method: .m_getCurrentDownloadTask)} - public static func eventPublisher() -> Verify { return Verify(method: .m_eventPublisher)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocks(`blocks`))} - public static func getDownloadTasks() -> Verify { return Verify(method: .m_getDownloadTasks)} - public static func getDownloadTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadTasksForCourse__courseId(`courseId`))} - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`))} - public static func cancelDownloading(task: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__task_task(`task`))} - public static func cancelDownloading(courseId: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseId(`courseId`))} - public static func cancelAllDownloading() -> Verify { return Verify(method: .m_cancelAllDownloading)} - public static func deleteAll() -> Verify { return Verify(method: .m_deleteAll)} - public static func fileUrl(for blockId: Parameter) -> Verify { return Verify(method: .m_fileUrl__for_blockId(`blockId`))} - public static func resumeDownloading() -> Verify { return Verify(method: .m_resumeDownloading)} - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_isLargeVideosSize__blocks_blocks(`blocks`))} - public static func removeAppSupportDirectoryUnusedContent() -> Verify { return Verify(method: .m_removeAppSupportDirectoryUnusedContent)} - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter) -> Verify { return Verify(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`))} - public static func downloadTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadTask__for_blockId(`blockId`))} - public static func getFreeDiskSpace() -> Verify { return Verify(method: .m_getFreeDiskSpace)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCurrentDownloadTask(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getCurrentDownloadTask, performs: perform) - } - public static func eventPublisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_eventPublisher, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), performs: perform) - } - public static func getDownloadTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadTasks, performs: perform) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, perform: @escaping (String, [CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), performs: perform) - } - public static func cancelDownloading(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__task_task(`task`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseId(`courseId`), performs: perform) - } - public static func cancelAllDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_cancelAllDownloading, performs: perform) - } - public static func deleteAll(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAll, performs: perform) - } - public static func fileUrl(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_fileUrl__for_blockId(`blockId`), performs: perform) - } - public static func resumeDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_resumeDownloading, performs: perform) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), performs: perform) - } - public static func removeAppSupportDirectoryUnusedContent(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeAppSupportDirectoryUnusedContent, performs: perform) - } - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter, perform: @escaping ([CourseBlock], String) -> Void) -> Perform { - return Perform(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`), performs: perform) - } - public static func downloadTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadTask__for_blockId(`blockId`), performs: perform) - } - public static func getFreeDiskSpace(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getFreeDiskSpace, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - OfflineSyncInteractorProtocol - -open class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func submitOfflineProgress(courseID: String, blockID: String, data: String) throws -> Bool { - addInvocation(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) - let perform = methodPerformValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) as? (String, String, String) -> Void - perform?(`courseID`, `blockID`, `data`) - var __value: Bool - do { - __value = try methodReturnValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - Failure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter, Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let lhsCourseid, let lhsBlockid, let lhsData), .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let rhsCourseid, let rhsBlockid, let rhsData)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsData, rhs: rhsData, with: matcher), lhsData, rhsData, "data")) - return Matcher.ComparisonResult(results) - } - } - - func intValue() -> Int { - switch self { - case let .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data: return ".submitOfflineProgress(courseID:blockID:data:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter) -> Verify { return Verify(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - diff --git a/Dashboard/DashboardTests/Generated/DashboardMocks.generated.swift b/Dashboard/DashboardTests/Generated/DashboardMocks.generated.swift new file mode 100644 index 000000000..c36c4bd2e --- /dev/null +++ b/Dashboard/DashboardTests/Generated/DashboardMocks.generated.swift @@ -0,0 +1,1940 @@ +/// +/// @Generated by Mockolo +/// + + + +import Alamofire +import Combine +@testable import Core +import CoreData +@testable import Dashboard +import Foundation +import OEXFoundation +import SwiftUI +import ZipArchive + + +public final class ConfigProtocolMock: ConfigProtocol, @unchecked Sendable { + public init() { } + public init(baseURL: URL = URL(fileURLWithPath: ""), baseSSOURL: URL = URL(fileURLWithPath: ""), ssoFinishedURL: URL = URL(fileURLWithPath: ""), ssoButtonTitle: [String: Any] = [String: Any](), oAuthClientId: String = "", tokenType: TokenType, feedbackEmail: String = "", appStoreLink: String = "", faq: URL? = nil, platformName: String = "", agreement: AgreementConfig, firebase: FirebaseConfig, facebook: FacebookConfig, microsoft: MicrosoftConfig, google: GoogleConfig, appleSignIn: AppleSignInConfig, features: FeaturesConfig, theme: ThemeConfig, uiComponents: UIComponentsConfig, discovery: DiscoveryConfig, dashboard: DashboardConfig, braze: BrazeConfig, branch: BranchConfig, program: DiscoveryConfig, experimentalFeatures: ExperimentalFeaturesConfig, URIScheme: String = "") { + self.baseURL = baseURL + self.baseSSOURL = baseSSOURL + self.ssoFinishedURL = ssoFinishedURL + self.ssoButtonTitle = ssoButtonTitle + self.oAuthClientId = oAuthClientId + self._tokenType = tokenType + self.feedbackEmail = feedbackEmail + self.appStoreLink = appStoreLink + self.faq = faq + self.platformName = platformName + self._agreement = agreement + self._firebase = firebase + self._facebook = facebook + self._microsoft = microsoft + self._google = google + self._appleSignIn = appleSignIn + self._features = features + self._theme = theme + self._uiComponents = uiComponents + self._discovery = discovery + self._dashboard = dashboard + self._braze = braze + self._branch = branch + self._program = program + self._experimentalFeatures = experimentalFeatures + self.URIScheme = URIScheme + } + + + + public var baseURL: URL = URL(fileURLWithPath: "") + + + public var baseSSOURL: URL = URL(fileURLWithPath: "") + + + public var ssoFinishedURL: URL = URL(fileURLWithPath: "") + + + public var ssoButtonTitle: [String: Any] = [String: Any]() + + + public var oAuthClientId: String = "" + + + private var _tokenType: TokenType! + public var tokenType: TokenType { + get { return _tokenType } + set { _tokenType = newValue } + } + + + public var feedbackEmail: String = "" + + + public var appStoreLink: String = "" + + + public var faq: URL? = nil + + + public var platformName: String = "" + + + private var _agreement: AgreementConfig! + public var agreement: AgreementConfig { + get { return _agreement } + set { _agreement = newValue } + } + + + private var _firebase: FirebaseConfig! + public var firebase: FirebaseConfig { + get { return _firebase } + set { _firebase = newValue } + } + + + private var _facebook: FacebookConfig! + public var facebook: FacebookConfig { + get { return _facebook } + set { _facebook = newValue } + } + + + private var _microsoft: MicrosoftConfig! + public var microsoft: MicrosoftConfig { + get { return _microsoft } + set { _microsoft = newValue } + } + + + private var _google: GoogleConfig! + public var google: GoogleConfig { + get { return _google } + set { _google = newValue } + } + + + private var _appleSignIn: AppleSignInConfig! + public var appleSignIn: AppleSignInConfig { + get { return _appleSignIn } + set { _appleSignIn = newValue } + } + + + private var _features: FeaturesConfig! + public var features: FeaturesConfig { + get { return _features } + set { _features = newValue } + } + + + private var _theme: ThemeConfig! + public var theme: ThemeConfig { + get { return _theme } + set { _theme = newValue } + } + + + private var _uiComponents: UIComponentsConfig! + public var uiComponents: UIComponentsConfig { + get { return _uiComponents } + set { _uiComponents = newValue } + } + + + private var _discovery: DiscoveryConfig! + public var discovery: DiscoveryConfig { + get { return _discovery } + set { _discovery = newValue } + } + + + private var _dashboard: DashboardConfig! + public var dashboard: DashboardConfig { + get { return _dashboard } + set { _dashboard = newValue } + } + + + private var _braze: BrazeConfig! + public var braze: BrazeConfig { + get { return _braze } + set { _braze = newValue } + } + + + private var _branch: BranchConfig! + public var branch: BranchConfig { + get { return _branch } + set { _branch = newValue } + } + + + private var _program: DiscoveryConfig! + public var program: DiscoveryConfig { + get { return _program } + set { _program = newValue } + } + + + private var _experimentalFeatures: ExperimentalFeaturesConfig! + public var experimentalFeatures: ExperimentalFeaturesConfig { + get { return _experimentalFeatures } + set { _experimentalFeatures = newValue } + } + + + public var URIScheme: String = "" +} + +public final class CoreAnalyticsMock: CoreAnalytics { + public init() { } + + + public private(set) var trackEventCallCount = 0 + public var trackEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackEventCallCount += 1 + if let trackEventHandler = trackEventHandler { + trackEventHandler(event, parameters) + } + + } + + public private(set) var trackEventBiValueCallCount = 0 + public var trackEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackEventBiValueCallCount += 1 + if let trackEventBiValueHandler = trackEventBiValueHandler { + trackEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var trackScreenEventCallCount = 0 + public var trackScreenEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackScreenEventCallCount += 1 + if let trackScreenEventHandler = trackScreenEventHandler { + trackScreenEventHandler(event, parameters) + } + + } + + public private(set) var trackScreenEventBiValueCallCount = 0 + public var trackScreenEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackScreenEventBiValueCallCount += 1 + if let trackScreenEventBiValueHandler = trackScreenEventBiValueHandler { + trackScreenEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var appreviewCallCount = 0 + public var appreviewHandler: ((AnalyticsEvent, EventBIValue, String?, Int?) -> ())? + public func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { + appreviewCallCount += 1 + if let appreviewHandler = appreviewHandler { + appreviewHandler(event, biValue, action, rating) + } + + } + + public private(set) var videoQualityChangedCallCount = 0 + public var videoQualityChangedHandler: ((AnalyticsEvent, EventBIValue, String, String) -> ())? + public func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { + videoQualityChangedCallCount += 1 + if let videoQualityChangedHandler = videoQualityChangedHandler { + videoQualityChangedHandler(event, bivalue, value, oldValue) + } + + } +} + +public final class CoreStorageMock: CoreStorage, @unchecked Sendable { + public init() { } + public init(accessToken: String? = nil, refreshToken: String? = nil, pushToken: String? = nil, appleSignFullName: String? = nil, appleSignEmail: String? = nil, cookiesDate: Date? = nil, reviewLastShownVersion: String? = nil, lastReviewDate: Date? = nil, user: DataLayer.User? = nil, userSettings: UserSettings? = nil, resetAppSupportDirectoryUserData: Bool? = nil, useRelativeDates: Bool = false, lastUsedSocialAuth: String? = nil, latestAvailableAppVersion: String? = nil, updateAppRequired: Bool = false) { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.pushToken = pushToken + self.appleSignFullName = appleSignFullName + self.appleSignEmail = appleSignEmail + self.cookiesDate = cookiesDate + self.reviewLastShownVersion = reviewLastShownVersion + self.lastReviewDate = lastReviewDate + self.user = user + self.userSettings = userSettings + self.resetAppSupportDirectoryUserData = resetAppSupportDirectoryUserData + self.useRelativeDates = useRelativeDates + self.lastUsedSocialAuth = lastUsedSocialAuth + self.latestAvailableAppVersion = latestAvailableAppVersion + self.updateAppRequired = updateAppRequired + } + + + public private(set) var accessTokenSetCallCount = 0 + public var accessToken: String? = nil { didSet { accessTokenSetCallCount += 1 } } + + public private(set) var refreshTokenSetCallCount = 0 + public var refreshToken: String? = nil { didSet { refreshTokenSetCallCount += 1 } } + + public private(set) var pushTokenSetCallCount = 0 + public var pushToken: String? = nil { didSet { pushTokenSetCallCount += 1 } } + + public private(set) var appleSignFullNameSetCallCount = 0 + public var appleSignFullName: String? = nil { didSet { appleSignFullNameSetCallCount += 1 } } + + public private(set) var appleSignEmailSetCallCount = 0 + public var appleSignEmail: String? = nil { didSet { appleSignEmailSetCallCount += 1 } } + + public private(set) var cookiesDateSetCallCount = 0 + public var cookiesDate: Date? = nil { didSet { cookiesDateSetCallCount += 1 } } + + public private(set) var reviewLastShownVersionSetCallCount = 0 + public var reviewLastShownVersion: String? = nil { didSet { reviewLastShownVersionSetCallCount += 1 } } + + public private(set) var lastReviewDateSetCallCount = 0 + public var lastReviewDate: Date? = nil { didSet { lastReviewDateSetCallCount += 1 } } + + public private(set) var userSetCallCount = 0 + public var user: DataLayer.User? = nil { didSet { userSetCallCount += 1 } } + + public private(set) var userSettingsSetCallCount = 0 + public var userSettings: UserSettings? = nil { didSet { userSettingsSetCallCount += 1 } } + + public private(set) var resetAppSupportDirectoryUserDataSetCallCount = 0 + public var resetAppSupportDirectoryUserData: Bool? = nil { didSet { resetAppSupportDirectoryUserDataSetCallCount += 1 } } + + public private(set) var useRelativeDatesSetCallCount = 0 + public var useRelativeDates: Bool = false { didSet { useRelativeDatesSetCallCount += 1 } } + + public private(set) var lastUsedSocialAuthSetCallCount = 0 + public var lastUsedSocialAuth: String? = nil { didSet { lastUsedSocialAuthSetCallCount += 1 } } + + public private(set) var latestAvailableAppVersionSetCallCount = 0 + public var latestAvailableAppVersion: String? = nil { didSet { latestAvailableAppVersionSetCallCount += 1 } } + + public private(set) var updateAppRequiredSetCallCount = 0 + public var updateAppRequired: Bool = false { didSet { updateAppRequiredSetCallCount += 1 } } + + private let clearState = MockoloMutex(MockoloHandlerState ()>()) + public var clearCallCount: Int { + return clearState.withLock(\.callCount) + } + public var clearHandler: (@Sendable () -> ())? { + get { clearState.withLock(\.handler) } + set { clearState.withLock { $0.handler = newValue } } + } + public func clear() { + let clearHandler = clearState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearHandler = clearHandler { + clearHandler() + } + + } +} + +public final class AuthInteractorProtocolMock: AuthInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let loginState = MockoloMutex(MockoloHandlerState User>()) + public var loginCallCount: Int { + return loginState.withLock(\.callCount) + } + public var loginHandler: (@Sendable (String, String) async throws -> User)? { + get { loginState.withLock(\.handler) } + set { loginState.withLock { $0.handler = newValue } } + } + public func login(username: String, password: String) async throws -> User { + let loginHandler = loginState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginHandler = loginHandler { + return try await loginHandler(username, password) + } + fatalError("loginHandler returns can't have a default value thus its handler must be set") + } + + private let loginExternalTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginExternalTokenCallCount: Int { + return loginExternalTokenState.withLock(\.callCount) + } + public var loginExternalTokenHandler: (@Sendable (String, String) async throws -> User)? { + get { loginExternalTokenState.withLock(\.handler) } + set { loginExternalTokenState.withLock { $0.handler = newValue } } + } + public func login(externalToken: String, backend: String) async throws -> User { + let loginExternalTokenHandler = loginExternalTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginExternalTokenHandler = loginExternalTokenHandler { + return try await loginExternalTokenHandler(externalToken, backend) + } + fatalError("loginExternalTokenHandler returns can't have a default value thus its handler must be set") + } + + private let loginSsoTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginSsoTokenCallCount: Int { + return loginSsoTokenState.withLock(\.callCount) + } + public var loginSsoTokenHandler: (@Sendable (String) async throws -> User)? { + get { loginSsoTokenState.withLock(\.handler) } + set { loginSsoTokenState.withLock { $0.handler = newValue } } + } + public func login(ssoToken: String) async throws -> User { + let loginSsoTokenHandler = loginSsoTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginSsoTokenHandler = loginSsoTokenHandler { + return try await loginSsoTokenHandler(ssoToken) + } + fatalError("loginSsoTokenHandler returns can't have a default value thus its handler must be set") + } + + private let resetPasswordState = MockoloMutex(MockoloHandlerState ResetPassword>()) + public var resetPasswordCallCount: Int { + return resetPasswordState.withLock(\.callCount) + } + public var resetPasswordHandler: (@Sendable (String) async throws -> ResetPassword)? { + get { resetPasswordState.withLock(\.handler) } + set { resetPasswordState.withLock { $0.handler = newValue } } + } + public func resetPassword(email: String) async throws -> ResetPassword { + let resetPasswordHandler = resetPasswordState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resetPasswordHandler = resetPasswordHandler { + return try await resetPasswordHandler(email) + } + fatalError("resetPasswordHandler returns can't have a default value thus its handler must be set") + } + + private let getCookiesState = MockoloMutex(MockoloHandlerState ()>()) + public var getCookiesCallCount: Int { + return getCookiesState.withLock(\.callCount) + } + public var getCookiesHandler: (@Sendable (Bool) async throws -> ())? { + get { getCookiesState.withLock(\.handler) } + set { getCookiesState.withLock { $0.handler = newValue } } + } + public func getCookies(force: Bool) async throws { + let getCookiesHandler = getCookiesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCookiesHandler = getCookiesHandler { + try await getCookiesHandler(force) + } + + } + + private let getRegistrationFieldsState = MockoloMutex(MockoloHandlerState [PickerFields]>()) + public var getRegistrationFieldsCallCount: Int { + return getRegistrationFieldsState.withLock(\.callCount) + } + public var getRegistrationFieldsHandler: (@Sendable () async throws -> [PickerFields])? { + get { getRegistrationFieldsState.withLock(\.handler) } + set { getRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func getRegistrationFields() async throws -> [PickerFields] { + let getRegistrationFieldsHandler = getRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getRegistrationFieldsHandler = getRegistrationFieldsHandler { + return try await getRegistrationFieldsHandler() + } + return [PickerFields]() + } + + private let registerUserState = MockoloMutex(MockoloHandlerState User>()) + public var registerUserCallCount: Int { + return registerUserState.withLock(\.callCount) + } + public var registerUserHandler: (@Sendable ([String: String], Bool) async throws -> User)? { + get { registerUserState.withLock(\.handler) } + set { registerUserState.withLock { $0.handler = newValue } } + } + public func registerUser(fields: [String: String], isSocial: Bool) async throws -> User { + let registerUserHandler = registerUserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let registerUserHandler = registerUserHandler { + return try await registerUserHandler(fields, isSocial) + } + fatalError("registerUserHandler returns can't have a default value thus its handler must be set") + } + + private let validateRegistrationFieldsState = MockoloMutex(MockoloHandlerState [String: String]>()) + public var validateRegistrationFieldsCallCount: Int { + return validateRegistrationFieldsState.withLock(\.callCount) + } + public var validateRegistrationFieldsHandler: (@Sendable ([String: String]) async throws -> [String: String])? { + get { validateRegistrationFieldsState.withLock(\.handler) } + set { validateRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func validateRegistrationFields(fields: [String: String]) async throws -> [String: String] { + let validateRegistrationFieldsHandler = validateRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let validateRegistrationFieldsHandler = validateRegistrationFieldsHandler { + return try await validateRegistrationFieldsHandler(fields) + } + return [String: String]() + } +} + +public final class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let submitOfflineProgressState = MockoloMutex(MockoloHandlerState Bool>()) + public var submitOfflineProgressCallCount: Int { + return submitOfflineProgressState.withLock(\.callCount) + } + public var submitOfflineProgressHandler: (@Sendable (String, String, String) async throws -> Bool)? { + get { submitOfflineProgressState.withLock(\.handler) } + set { submitOfflineProgressState.withLock { $0.handler = newValue } } + } + public func submitOfflineProgress(courseID: String, blockID: String, data: String) async throws -> Bool { + let submitOfflineProgressHandler = submitOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let submitOfflineProgressHandler = submitOfflineProgressHandler { + return try await submitOfflineProgressHandler(courseID, blockID, data) + } + return false + } +} + +public final class WebviewCookiesUpdateProtocolMock: WebviewCookiesUpdateProtocol { + public init() { } + public init(authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock(), cookiesReady: Bool = false, updatingCookies: Bool = false, errorMessage: String? = nil) { + self.authInteractor = authInteractor + self.cookiesReady = cookiesReady + self.updatingCookies = updatingCookies + self.errorMessage = errorMessage + } + + + + public var authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock() + + public private(set) var cookiesReadySetCallCount = 0 + public var cookiesReady: Bool = false { didSet { cookiesReadySetCallCount += 1 } } + + public private(set) var updatingCookiesSetCallCount = 0 + public var updatingCookies: Bool = false { didSet { updatingCookiesSetCallCount += 1 } } + + public private(set) var errorMessageSetCallCount = 0 + public var errorMessage: String? = nil { didSet { errorMessageSetCallCount += 1 } } + + public private(set) var updateCookiesCallCount = 0 + public var updateCookiesHandler: ((Bool, Int) async -> ())? + public func updateCookies(force: Bool, retryCount: Int) async { + updateCookiesCallCount += 1 + if let updateCookiesHandler = updateCookiesHandler { + await updateCookiesHandler(force, retryCount) + } + + } +} + +public final class BaseRouterMock: BaseRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class CalendarManagerProtocolMock: CalendarManagerProtocol, @unchecked Sendable { + public init() { } + + + private let createCalendarIfNeededState = MockoloMutex(MockoloHandlerState ()>()) + public var createCalendarIfNeededCallCount: Int { + return createCalendarIfNeededState.withLock(\.callCount) + } + public var createCalendarIfNeededHandler: (@Sendable () -> ())? { + get { createCalendarIfNeededState.withLock(\.handler) } + set { createCalendarIfNeededState.withLock { $0.handler = newValue } } + } + public func createCalendarIfNeeded() { + let createCalendarIfNeededHandler = createCalendarIfNeededState.withLock { state in + state.callCount += 1 + return state.handler + } + if let createCalendarIfNeededHandler = createCalendarIfNeededHandler { + createCalendarIfNeededHandler() + } + + } + + private let filterCoursesBySelectedState = MockoloMutex(MockoloHandlerState [CourseForSync]>()) + public var filterCoursesBySelectedCallCount: Int { + return filterCoursesBySelectedState.withLock(\.callCount) + } + public var filterCoursesBySelectedHandler: (@Sendable ([CourseForSync]) async -> [CourseForSync])? { + get { filterCoursesBySelectedState.withLock(\.handler) } + set { filterCoursesBySelectedState.withLock { $0.handler = newValue } } + } + public func filterCoursesBySelected(fetchedCourses: [CourseForSync]) async -> [CourseForSync] { + let filterCoursesBySelectedHandler = filterCoursesBySelectedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let filterCoursesBySelectedHandler = filterCoursesBySelectedHandler { + return await filterCoursesBySelectedHandler(fetchedCourses) + } + return [CourseForSync]() + } + + private let removeOldCalendarState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOldCalendarCallCount: Int { + return removeOldCalendarState.withLock(\.callCount) + } + public var removeOldCalendarHandler: (@Sendable () -> ())? { + get { removeOldCalendarState.withLock(\.handler) } + set { removeOldCalendarState.withLock { $0.handler = newValue } } + } + public func removeOldCalendar() { + let removeOldCalendarHandler = removeOldCalendarState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOldCalendarHandler = removeOldCalendarHandler { + removeOldCalendarHandler() + } + + } + + private let removeOutdatedEventsState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOutdatedEventsCallCount: Int { + return removeOutdatedEventsState.withLock(\.callCount) + } + public var removeOutdatedEventsHandler: (@Sendable (String) async -> ())? { + get { removeOutdatedEventsState.withLock(\.handler) } + set { removeOutdatedEventsState.withLock { $0.handler = newValue } } + } + public func removeOutdatedEvents(courseID: String) async { + let removeOutdatedEventsHandler = removeOutdatedEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOutdatedEventsHandler = removeOutdatedEventsHandler { + await removeOutdatedEventsHandler(courseID) + } + + } + + private let syncCourseState = MockoloMutex(MockoloHandlerState ()>()) + public var syncCourseCallCount: Int { + return syncCourseState.withLock(\.callCount) + } + public var syncCourseHandler: (@Sendable (String, String, CourseDates) async -> ())? { + get { syncCourseState.withLock(\.handler) } + set { syncCourseState.withLock { $0.handler = newValue } } + } + public func syncCourse(courseID: String, courseName: String, dates: CourseDates) async { + let syncCourseHandler = syncCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let syncCourseHandler = syncCourseHandler { + await syncCourseHandler(courseID, courseName, dates) + } + + } + + private let requestAccessState = MockoloMutex(MockoloHandlerState Bool>()) + public var requestAccessCallCount: Int { + return requestAccessState.withLock(\.callCount) + } + public var requestAccessHandler: (@Sendable () async -> Bool)? { + get { requestAccessState.withLock(\.handler) } + set { requestAccessState.withLock { $0.handler = newValue } } + } + public func requestAccess() async -> Bool { + let requestAccessHandler = requestAccessState.withLock { state in + state.callCount += 1 + return state.handler + } + if let requestAccessHandler = requestAccessHandler { + return await requestAccessHandler() + } + return false + } + + private let courseStatusState = MockoloMutex(MockoloHandlerState SyncStatus>()) + public var courseStatusCallCount: Int { + return courseStatusState.withLock(\.callCount) + } + public var courseStatusHandler: (@Sendable (String) async -> SyncStatus)? { + get { courseStatusState.withLock(\.handler) } + set { courseStatusState.withLock { $0.handler = newValue } } + } + public func courseStatus(courseID: String) async -> SyncStatus { + let courseStatusHandler = courseStatusState.withLock { state in + state.callCount += 1 + return state.handler + } + if let courseStatusHandler = courseStatusHandler { + return await courseStatusHandler(courseID) + } + fatalError("courseStatusHandler returns can't have a default value thus its handler must be set") + } + + private let clearAllDataState = MockoloMutex(MockoloHandlerState ()>()) + public var clearAllDataCallCount: Int { + return clearAllDataState.withLock(\.callCount) + } + public var clearAllDataHandler: (@Sendable (Bool) async -> ())? { + get { clearAllDataState.withLock(\.handler) } + set { clearAllDataState.withLock { $0.handler = newValue } } + } + public func clearAllData(removeCalendar: Bool) async { + let clearAllDataHandler = clearAllDataState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearAllDataHandler = clearAllDataHandler { + await clearAllDataHandler(removeCalendar) + } + + } + + private let isDatesChangedState = MockoloMutex(MockoloHandlerState Bool>()) + public var isDatesChangedCallCount: Int { + return isDatesChangedState.withLock(\.callCount) + } + public var isDatesChangedHandler: (@Sendable (String, String) async -> Bool)? { + get { isDatesChangedState.withLock(\.handler) } + set { isDatesChangedState.withLock { $0.handler = newValue } } + } + public func isDatesChanged(courseID: String, checksum: String) async -> Bool { + let isDatesChangedHandler = isDatesChangedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isDatesChangedHandler = isDatesChangedHandler { + return await isDatesChangedHandler(courseID, checksum) + } + return false + } +} + +public final class DashboardAnalyticsMock: DashboardAnalytics { + public init() { } + + + public private(set) var dashboardCourseClickedCallCount = 0 + public var dashboardCourseClickedHandler: ((String, String) -> ())? + public func dashboardCourseClicked(courseID: String, courseName: String) { + dashboardCourseClickedCallCount += 1 + if let dashboardCourseClickedHandler = dashboardCourseClickedHandler { + dashboardCourseClickedHandler(courseID, courseName) + } + + } + + public private(set) var mainProgramsClickedCallCount = 0 + public var mainProgramsClickedHandler: (() -> ())? + public func mainProgramsClicked() { + mainProgramsClickedCallCount += 1 + if let mainProgramsClickedHandler = mainProgramsClickedHandler { + mainProgramsClickedHandler() + } + + } + + public private(set) var mainCoursesClickedCallCount = 0 + public var mainCoursesClickedHandler: (() -> ())? + public func mainCoursesClicked() { + mainCoursesClickedCallCount += 1 + if let mainCoursesClickedHandler = mainCoursesClickedHandler { + mainCoursesClickedHandler() + } + + } +} + +public final class CorePersistenceProtocolMock: CorePersistenceProtocol, @unchecked Sendable { + public init() { } + + + private let setState = MockoloMutex(MockoloHandlerState ()>()) + public var setCallCount: Int { + return setState.withLock(\.callCount) + } + public var setHandler: (@Sendable (Int) -> ())? { + get { setState.withLock(\.handler) } + set { setState.withLock { $0.handler = newValue } } + } + public func set(userId: Int) { + let setHandler = setState.withLock { state in + state.callCount += 1 + return state.handler + } + if let setHandler = setHandler { + setHandler(userId) + } + + } + + private let getUserIDState = MockoloMutex(MockoloHandlerState Int?>()) + public var getUserIDCallCount: Int { + return getUserIDState.withLock(\.callCount) + } + public var getUserIDHandler: (@Sendable () -> Int?)? { + get { getUserIDState.withLock(\.handler) } + set { getUserIDState.withLock { $0.handler = newValue } } + } + public func getUserID() -> Int? { + let getUserIDHandler = getUserIDState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getUserIDHandler = getUserIDHandler { + return getUserIDHandler() + } + return nil + } + + private let publisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var publisherCallCount: Int { + return publisherState.withLock(\.callCount) + } + public var publisherHandler: (@Sendable () throws -> AnyPublisher)? { + get { publisherState.withLock(\.handler) } + set { publisherState.withLock { $0.handler = newValue } } + } + public func publisher() throws -> AnyPublisher { + let publisherHandler = publisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let publisherHandler = publisherHandler { + return try publisherHandler() + } + fatalError("publisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([DownloadDataTask]) -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(tasks: [DownloadDataTask]) { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + addToDownloadQueueHandler(tasks) + } + + } + + private let saveOfflineProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var saveOfflineProgressCallCount: Int { + return saveOfflineProgressState.withLock(\.callCount) + } + public var saveOfflineProgressHandler: (@Sendable (OfflineProgress) async -> ())? { + get { saveOfflineProgressState.withLock(\.handler) } + set { saveOfflineProgressState.withLock { $0.handler = newValue } } + } + public func saveOfflineProgress(progress: OfflineProgress) async { + let saveOfflineProgressHandler = saveOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveOfflineProgressHandler = saveOfflineProgressHandler { + await saveOfflineProgressHandler(progress) + } + + } + + private let loadProgressState = MockoloMutex(MockoloHandlerState OfflineProgress?>()) + public var loadProgressCallCount: Int { + return loadProgressState.withLock(\.callCount) + } + public var loadProgressHandler: (@Sendable (String) async -> OfflineProgress?)? { + get { loadProgressState.withLock(\.handler) } + set { loadProgressState.withLock { $0.handler = newValue } } + } + public func loadProgress(for blockID: String) async -> OfflineProgress? { + let loadProgressHandler = loadProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadProgressHandler = loadProgressHandler { + return await loadProgressHandler(blockID) + } + return nil + } + + private let loadAllOfflineProgressState = MockoloMutex(MockoloHandlerState [OfflineProgress]>()) + public var loadAllOfflineProgressCallCount: Int { + return loadAllOfflineProgressState.withLock(\.callCount) + } + public var loadAllOfflineProgressHandler: (@Sendable () async -> [OfflineProgress])? { + get { loadAllOfflineProgressState.withLock(\.handler) } + set { loadAllOfflineProgressState.withLock { $0.handler = newValue } } + } + public func loadAllOfflineProgress() async -> [OfflineProgress] { + let loadAllOfflineProgressHandler = loadAllOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadAllOfflineProgressHandler = loadAllOfflineProgressHandler { + return await loadAllOfflineProgressHandler() + } + return [OfflineProgress]() + } + + private let deleteProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteProgressCallCount: Int { + return deleteProgressState.withLock(\.callCount) + } + public var deleteProgressHandler: (@Sendable (String) async -> ())? { + get { deleteProgressState.withLock(\.handler) } + set { deleteProgressState.withLock { $0.handler = newValue } } + } + public func deleteProgress(for blockID: String) async { + let deleteProgressHandler = deleteProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteProgressHandler = deleteProgressHandler { + await deleteProgressHandler(blockID) + } + + } + + private let deleteAllProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllProgressCallCount: Int { + return deleteAllProgressState.withLock(\.callCount) + } + public var deleteAllProgressHandler: (@Sendable () async -> ())? { + get { deleteAllProgressState.withLock(\.handler) } + set { deleteAllProgressState.withLock { $0.handler = newValue } } + } + public func deleteAllProgress() async { + let deleteAllProgressHandler = deleteAllProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllProgressHandler = deleteAllProgressHandler { + await deleteAllProgressHandler() + } + + } + + private let addToDownloadQueueBlocksState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueBlocksCallCount: Int { + return addToDownloadQueueBlocksState.withLock(\.callCount) + } + public var addToDownloadQueueBlocksHandler: (@Sendable ([CourseBlock], DownloadQuality) -> ())? { + get { addToDownloadQueueBlocksState.withLock(\.handler) } + set { addToDownloadQueueBlocksState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { + let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksHandler { + addToDownloadQueueBlocksHandler(blocks, downloadQuality) + } + + } + + private let updateTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var updateTaskCallCount: Int { + return updateTaskState.withLock(\.callCount) + } + public var updateTaskHandler: (@Sendable (DownloadDataTask) -> ())? { + get { updateTaskState.withLock(\.handler) } + set { updateTaskState.withLock { $0.handler = newValue } } + } + public func updateTask(task: DownloadDataTask) { + let updateTaskHandler = updateTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateTaskHandler = updateTaskHandler { + updateTaskHandler(task) + } + + } + + private let downloadDataTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadDataTaskCallCount: Int { + return downloadDataTaskState.withLock(\.callCount) + } + public var downloadDataTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadDataTaskState.withLock(\.handler) } + set { downloadDataTaskState.withLock { $0.handler = newValue } } + } + public func downloadDataTask(for blockId: String) async -> DownloadDataTask? { + let downloadDataTaskHandler = downloadDataTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadDataTaskHandler = downloadDataTaskHandler { + return await downloadDataTaskHandler(blockId) + } + return nil + } + + private let getDownloadDataTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksCallCount: Int { + return getDownloadDataTasksState.withLock(\.callCount) + } + public var getDownloadDataTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadDataTasksState.withLock(\.handler) } + set { getDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasks() async -> [DownloadDataTask] { + let getDownloadDataTasksHandler = getDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksHandler = getDownloadDataTasksHandler { + return await getDownloadDataTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadDataTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksForCourseCallCount: Int { + return getDownloadDataTasksForCourseState.withLock(\.callCount) + } + public var getDownloadDataTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadDataTasksForCourseState.withLock(\.handler) } + set { getDownloadDataTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseHandler { + return await getDownloadDataTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let deleteDownloadDataTasksState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteDownloadDataTasksCallCount: Int { + return deleteDownloadDataTasksState.withLock(\.callCount) + } + public var deleteDownloadDataTasksHandler: (@Sendable ([String]) -> ())? { + get { deleteDownloadDataTasksState.withLock(\.handler) } + set { deleteDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func deleteDownloadDataTasks(ids: [String]) { + let deleteDownloadDataTasksHandler = deleteDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteDownloadDataTasksHandler = deleteDownloadDataTasksHandler { + deleteDownloadDataTasksHandler(ids) + } + + } +} + +public final class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseBlocksCallCount: Int { + return getCourseBlocksState.withLock(\.callCount) + } + public var getCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getCourseBlocksState.withLock(\.handler) } + set { getCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseBlocks(courseID: String) async throws -> CourseStructure { + let getCourseBlocksHandler = getCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseBlocksHandler = getCourseBlocksHandler { + return try await getCourseBlocksHandler(courseID) + } + fatalError("getCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getLoadedCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getLoadedCourseBlocksCallCount: Int { + return getLoadedCourseBlocksState.withLock(\.callCount) + } + public var getLoadedCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getLoadedCourseBlocksState.withLock(\.handler) } + set { getLoadedCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure { + let getLoadedCourseBlocksHandler = getLoadedCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseBlocksHandler = getLoadedCourseBlocksHandler { + return try await getLoadedCourseBlocksHandler(courseID) + } + fatalError("getLoadedCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let shiftDueDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var shiftDueDatesCallCount: Int { + return shiftDueDatesState.withLock(\.callCount) + } + public var shiftDueDatesHandler: (@Sendable (String) async throws -> ())? { + get { shiftDueDatesState.withLock(\.handler) } + set { shiftDueDatesState.withLock { $0.handler = newValue } } + } + public func shiftDueDates(courseID: String) async throws { + let shiftDueDatesHandler = shiftDueDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let shiftDueDatesHandler = shiftDueDatesHandler { + try await shiftDueDatesHandler(courseID) + } + + } +} + +public final class DashboardInteractorProtocolMock: DashboardInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let getEnrollmentsState = MockoloMutex(MockoloHandlerState [CourseItem]>()) + public var getEnrollmentsCallCount: Int { + return getEnrollmentsState.withLock(\.callCount) + } + public var getEnrollmentsHandler: (@Sendable (Int) async throws -> [CourseItem])? { + get { getEnrollmentsState.withLock(\.handler) } + set { getEnrollmentsState.withLock { $0.handler = newValue } } + } + public func getEnrollments(page: Int) async throws -> [CourseItem] { + let getEnrollmentsHandler = getEnrollmentsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getEnrollmentsHandler = getEnrollmentsHandler { + return try await getEnrollmentsHandler(page) + } + return [CourseItem]() + } + + private let getEnrollmentsOfflineState = MockoloMutex(MockoloHandlerState [CourseItem]>()) + public var getEnrollmentsOfflineCallCount: Int { + return getEnrollmentsOfflineState.withLock(\.callCount) + } + public var getEnrollmentsOfflineHandler: (@Sendable () async throws -> [CourseItem])? { + get { getEnrollmentsOfflineState.withLock(\.handler) } + set { getEnrollmentsOfflineState.withLock { $0.handler = newValue } } + } + public func getEnrollmentsOffline() async throws -> [CourseItem] { + let getEnrollmentsOfflineHandler = getEnrollmentsOfflineState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getEnrollmentsOfflineHandler = getEnrollmentsOfflineHandler { + return try await getEnrollmentsOfflineHandler() + } + return [CourseItem]() + } + + private let getPrimaryEnrollmentState = MockoloMutex(MockoloHandlerState PrimaryEnrollment>()) + public var getPrimaryEnrollmentCallCount: Int { + return getPrimaryEnrollmentState.withLock(\.callCount) + } + public var getPrimaryEnrollmentHandler: (@Sendable (Int) async throws -> PrimaryEnrollment)? { + get { getPrimaryEnrollmentState.withLock(\.handler) } + set { getPrimaryEnrollmentState.withLock { $0.handler = newValue } } + } + public func getPrimaryEnrollment(pageSize: Int) async throws -> PrimaryEnrollment { + let getPrimaryEnrollmentHandler = getPrimaryEnrollmentState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getPrimaryEnrollmentHandler = getPrimaryEnrollmentHandler { + return try await getPrimaryEnrollmentHandler(pageSize) + } + fatalError("getPrimaryEnrollmentHandler returns can't have a default value thus its handler must be set") + } + + private let getPrimaryEnrollmentOfflineState = MockoloMutex(MockoloHandlerState PrimaryEnrollment>()) + public var getPrimaryEnrollmentOfflineCallCount: Int { + return getPrimaryEnrollmentOfflineState.withLock(\.callCount) + } + public var getPrimaryEnrollmentOfflineHandler: (@Sendable () async throws -> PrimaryEnrollment)? { + get { getPrimaryEnrollmentOfflineState.withLock(\.handler) } + set { getPrimaryEnrollmentOfflineState.withLock { $0.handler = newValue } } + } + public func getPrimaryEnrollmentOffline() async throws -> PrimaryEnrollment { + let getPrimaryEnrollmentOfflineHandler = getPrimaryEnrollmentOfflineState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getPrimaryEnrollmentOfflineHandler = getPrimaryEnrollmentOfflineHandler { + return try await getPrimaryEnrollmentOfflineHandler() + } + fatalError("getPrimaryEnrollmentOfflineHandler returns can't have a default value thus its handler must be set") + } + + private let getAllCoursesState = MockoloMutex(MockoloHandlerState PrimaryEnrollment>()) + public var getAllCoursesCallCount: Int { + return getAllCoursesState.withLock(\.callCount) + } + public var getAllCoursesHandler: (@Sendable (String, Int) async throws -> PrimaryEnrollment)? { + get { getAllCoursesState.withLock(\.handler) } + set { getAllCoursesState.withLock { $0.handler = newValue } } + } + public func getAllCourses(filteredBy: String, page: Int) async throws -> PrimaryEnrollment { + let getAllCoursesHandler = getAllCoursesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getAllCoursesHandler = getAllCoursesHandler { + return try await getAllCoursesHandler(filteredBy, page) + } + fatalError("getAllCoursesHandler returns can't have a default value thus its handler must be set") + } +} + +public final class ConnectivityProtocolMock: ConnectivityProtocol, @unchecked Sendable { + public init() { } + public init(isInternetAvaliable: Bool = false, isMobileData: Bool = false) { + self.isInternetAvaliable = isInternetAvaliable + self.isMobileData = isMobileData + } + + + + public var isInternetAvaliable: Bool = false + + + public var isMobileData: Bool = false + + + private var _internetReachableSubject: CurrentValueSubject! + public var internetReachableSubject: CurrentValueSubject { + get { return _internetReachableSubject } + set { _internetReachableSubject = newValue } + } +} + +public final class DownloadManagerProtocolMock: DownloadManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCurrentDownloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var getCurrentDownloadTaskCallCount: Int { + return getCurrentDownloadTaskState.withLock(\.callCount) + } + public var getCurrentDownloadTaskHandler: (@Sendable () async -> DownloadDataTask?)? { + get { getCurrentDownloadTaskState.withLock(\.handler) } + set { getCurrentDownloadTaskState.withLock { $0.handler = newValue } } + } + public func getCurrentDownloadTask() async -> DownloadDataTask? { + let getCurrentDownloadTaskHandler = getCurrentDownloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCurrentDownloadTaskHandler = getCurrentDownloadTaskHandler { + return await getCurrentDownloadTaskHandler() + } + return nil + } + + private let eventPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var eventPublisherCallCount: Int { + return eventPublisherState.withLock(\.callCount) + } + public var eventPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { eventPublisherState.withLock(\.handler) } + set { eventPublisherState.withLock { $0.handler = newValue } } + } + public func eventPublisher() -> AnyPublisher { + let eventPublisherHandler = eventPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let eventPublisherHandler = eventPublisherHandler { + return eventPublisherHandler() + } + fatalError("eventPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([CourseBlock]) async throws -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock]) async throws { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + try await addToDownloadQueueHandler(blocks) + } + + } + + private let getDownloadTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksCallCount: Int { + return getDownloadTasksState.withLock(\.callCount) + } + public var getDownloadTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadTasksState.withLock(\.handler) } + set { getDownloadTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadTasks() async -> [DownloadDataTask] { + let getDownloadTasksHandler = getDownloadTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksHandler = getDownloadTasksHandler { + return await getDownloadTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksForCourseCallCount: Int { + return getDownloadTasksForCourseState.withLock(\.callCount) + } + public var getDownloadTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadTasksForCourseState.withLock(\.handler) } + set { getDownloadTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadTasksForCourseHandler = getDownloadTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksForCourseHandler = getDownloadTasksForCourseHandler { + return await getDownloadTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let cancelDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCallCount: Int { + return cancelDownloadingState.withLock(\.callCount) + } + public var cancelDownloadingHandler: (@Sendable (String, [CourseBlock]) async throws -> ())? { + get { cancelDownloadingState.withLock(\.handler) } + set { cancelDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String, blocks: [CourseBlock]) async throws { + let cancelDownloadingHandler = cancelDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingHandler = cancelDownloadingHandler { + try await cancelDownloadingHandler(courseId, blocks) + } + + } + + private let cancelDownloadingTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingTaskCallCount: Int { + return cancelDownloadingTaskState.withLock(\.callCount) + } + public var cancelDownloadingTaskHandler: (@Sendable (DownloadDataTask) async throws -> ())? { + get { cancelDownloadingTaskState.withLock(\.handler) } + set { cancelDownloadingTaskState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(task: DownloadDataTask) async throws { + let cancelDownloadingTaskHandler = cancelDownloadingTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingTaskHandler = cancelDownloadingTaskHandler { + try await cancelDownloadingTaskHandler(task) + } + + } + + private let cancelDownloadingCourseIdState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCourseIdCallCount: Int { + return cancelDownloadingCourseIdState.withLock(\.callCount) + } + public var cancelDownloadingCourseIdHandler: (@Sendable (String) async throws -> ())? { + get { cancelDownloadingCourseIdState.withLock(\.handler) } + set { cancelDownloadingCourseIdState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String) async throws { + let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdHandler { + try await cancelDownloadingCourseIdHandler(courseId) + } + + } + + private let cancelAllDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelAllDownloadingCallCount: Int { + return cancelAllDownloadingState.withLock(\.callCount) + } + public var cancelAllDownloadingHandler: (@Sendable () async throws -> ())? { + get { cancelAllDownloadingState.withLock(\.handler) } + set { cancelAllDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelAllDownloading() async throws { + let cancelAllDownloadingHandler = cancelAllDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelAllDownloadingHandler = cancelAllDownloadingHandler { + try await cancelAllDownloadingHandler() + } + + } + + private let deleteAllState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllCallCount: Int { + return deleteAllState.withLock(\.callCount) + } + public var deleteAllHandler: (@Sendable () async -> ())? { + get { deleteAllState.withLock(\.handler) } + set { deleteAllState.withLock { $0.handler = newValue } } + } + public func deleteAll() async { + let deleteAllHandler = deleteAllState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllHandler = deleteAllHandler { + await deleteAllHandler() + } + + } + + private let fileUrlState = MockoloMutex(MockoloHandlerState URL?>()) + public var fileUrlCallCount: Int { + return fileUrlState.withLock(\.callCount) + } + public var fileUrlHandler: (@Sendable (String) async -> URL?)? { + get { fileUrlState.withLock(\.handler) } + set { fileUrlState.withLock { $0.handler = newValue } } + } + public func fileUrl(for blockId: String) async -> URL? { + let fileUrlHandler = fileUrlState.withLock { state in + state.callCount += 1 + return state.handler + } + if let fileUrlHandler = fileUrlHandler { + return await fileUrlHandler(blockId) + } + return nil + } + + private let resumeDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var resumeDownloadingCallCount: Int { + return resumeDownloadingState.withLock(\.callCount) + } + public var resumeDownloadingHandler: (@Sendable () async throws -> ())? { + get { resumeDownloadingState.withLock(\.handler) } + set { resumeDownloadingState.withLock { $0.handler = newValue } } + } + public func resumeDownloading() async throws { + let resumeDownloadingHandler = resumeDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resumeDownloadingHandler = resumeDownloadingHandler { + try await resumeDownloadingHandler() + } + + } + + private let isLargeVideosSizeState = MockoloMutex(MockoloHandlerState Bool>()) + public var isLargeVideosSizeCallCount: Int { + return isLargeVideosSizeState.withLock(\.callCount) + } + public var isLargeVideosSizeHandler: (@Sendable ([CourseBlock]) async -> Bool)? { + get { isLargeVideosSizeState.withLock(\.handler) } + set { isLargeVideosSizeState.withLock { $0.handler = newValue } } + } + public func isLargeVideosSize(blocks: [CourseBlock]) async -> Bool { + let isLargeVideosSizeHandler = isLargeVideosSizeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isLargeVideosSizeHandler = isLargeVideosSizeHandler { + return await isLargeVideosSizeHandler(blocks) + } + return false + } + + private let removeAppSupportDirectoryUnusedContentState = MockoloMutex(MockoloHandlerState ()>()) + public var removeAppSupportDirectoryUnusedContentCallCount: Int { + return removeAppSupportDirectoryUnusedContentState.withLock(\.callCount) + } + public var removeAppSupportDirectoryUnusedContentHandler: (@Sendable () -> ())? { + get { removeAppSupportDirectoryUnusedContentState.withLock(\.handler) } + set { removeAppSupportDirectoryUnusedContentState.withLock { $0.handler = newValue } } + } + public func removeAppSupportDirectoryUnusedContent() { + let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentHandler { + removeAppSupportDirectoryUnusedContentHandler() + } + + } + + private let deleteState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteCallCount: Int { + return deleteState.withLock(\.callCount) + } + public var deleteHandler: (@Sendable ([CourseBlock], String) async -> ())? { + get { deleteState.withLock(\.handler) } + set { deleteState.withLock { $0.handler = newValue } } + } + public func delete(blocks: [CourseBlock], courseId: String) async { + let deleteHandler = deleteState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteHandler = deleteHandler { + await deleteHandler(blocks, courseId) + } + + } + + private let downloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadTaskCallCount: Int { + return downloadTaskState.withLock(\.callCount) + } + public var downloadTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadTaskState.withLock(\.handler) } + set { downloadTaskState.withLock { $0.handler = newValue } } + } + public func downloadTask(for blockId: String) async -> DownloadDataTask? { + let downloadTaskHandler = downloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadTaskHandler = downloadTaskHandler { + return await downloadTaskHandler(blockId) + } + return nil + } + + private let getFreeDiskSpaceState = MockoloMutex(MockoloHandlerState Int?>()) + public var getFreeDiskSpaceCallCount: Int { + return getFreeDiskSpaceState.withLock(\.callCount) + } + public var getFreeDiskSpaceHandler: (@Sendable () -> Int?)? { + get { getFreeDiskSpaceState.withLock(\.handler) } + set { getFreeDiskSpaceState.withLock { $0.handler = newValue } } + } + public func getFreeDiskSpace() -> Int? { + let getFreeDiskSpaceHandler = getFreeDiskSpaceState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getFreeDiskSpaceHandler = getFreeDiskSpaceHandler { + return getFreeDiskSpaceHandler() + } + return nil + } +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { + print("At \(function), the captured arguments are not Sendable, it is not concurrency-safe.") +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { +} + +/// Will be replaced to `Synchronization.Mutex` in future. +fileprivate final class MockoloMutex: @unchecked Sendable { + private let lock = NSLock() + private var value: Value + init(_ initialValue: Value) { + self.value = initialValue + } +#if compiler(>=6.0) + borrowing func withLock(_ body: (inout sending Value) throws(E) -> Result) throws(E) -> sending Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#else + func withLock(_ body: (inout Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#endif +} + +fileprivate struct MockoloUnsafeTransfer: @unchecked Sendable { + var value: Value + init(_ value: Value) { + self.value = value + } +} + +fileprivate struct MockoloHandlerState { + var argValues: [MockoloUnsafeTransfer] = [] + var handler: Handler? = nil + var callCount: Int = 0 +} + diff --git a/Dashboard/DashboardTests/Presentation/AllCoursesViewModelTests.swift b/Dashboard/DashboardTests/Presentation/AllCoursesViewModelTests.swift index 7dddaeff4..71828a2d2 100644 --- a/Dashboard/DashboardTests/Presentation/AllCoursesViewModelTests.swift +++ b/Dashboard/DashboardTests/Presentation/AllCoursesViewModelTests.swift @@ -5,8 +5,6 @@ // Created by Ivan Stepanok on 30.10.2024. // - -import SwiftyMocky import XCTest @testable import Core @testable import Dashboard @@ -15,12 +13,12 @@ import SwiftUI @MainActor final class AllCoursesViewModelTests: XCTestCase { - + var interactor: DashboardInteractorProtocolMock! var connectivity: ConnectivityProtocolMock! var analytics: DashboardAnalyticsMock! var storage: CoreStorageMock! - + override func setUp() { super.setUp() interactor = DashboardInteractorProtocolMock() @@ -28,9 +26,9 @@ final class AllCoursesViewModelTests: XCTestCase { analytics = DashboardAnalyticsMock() storage = CoreStorageMock() } - + let mockEnrollment = PrimaryEnrollment( - primaryCourse: PrimaryCourse.init( + primaryCourse: PrimaryCourse( name: "Primary Course", org: "OpenEdX", courseID: "1", @@ -46,7 +44,7 @@ final class AllCoursesViewModelTests: XCTestCase { resumeTitle: nil ), courses: [ - CourseItem.init( + CourseItem( name: "Course", org: "OpenEdX", shortDescription: "short description", @@ -63,7 +61,7 @@ final class AllCoursesViewModelTests: XCTestCase { progressEarned: 0, progressPossible: 2 ), - CourseItem.init( + CourseItem( name: "Course", org: "OpenEdX", shortDescription: "short description", @@ -80,7 +78,7 @@ final class AllCoursesViewModelTests: XCTestCase { progressEarned: 0, progressPossible: 2 ), - CourseItem.init( + CourseItem( name: "Course", org: "OpenEdX", shortDescription: "short description", @@ -101,7 +99,7 @@ final class AllCoursesViewModelTests: XCTestCase { totalPages: 2, count: 1 ) - + func testGetCoursesSuccess() async throws { // Given let viewModel = AllCoursesViewModel( @@ -110,21 +108,21 @@ final class AllCoursesViewModelTests: XCTestCase { analytics: analytics, storage: storage ) - - Given(interactor, .getAllCourses(filteredBy: .any, page: .any, willReturn: mockEnrollment)) - + + interactor.getAllCoursesHandler = { _, _ in self.mockEnrollment } + // When await viewModel.getCourses(page: 1) - + // Then - Verify(interactor, 1, .getAllCourses(filteredBy: .any, page: .value(1))) + XCTAssertEqual(interactor.getAllCoursesCallCount, 1) XCTAssertEqual(viewModel.myEnrollments?.courses.count, 3) XCTAssertEqual(viewModel.nextPage, 2) XCTAssertEqual(viewModel.totalPages, 2) XCTAssertFalse(viewModel.fetchInProgress) XCTAssertFalse(viewModel.showError) } - + func testGetCoursesWithPagination() async throws { // Given let viewModel = AllCoursesViewModel( @@ -133,18 +131,18 @@ final class AllCoursesViewModelTests: XCTestCase { analytics: analytics, storage: storage ) - - Given(interactor, .getAllCourses(filteredBy: .any, page: .any, willReturn: mockEnrollment)) - + + interactor.getAllCoursesHandler = { _, _ in self.mockEnrollment } + // When await viewModel.getCourses(page: 1) await viewModel.getCourses(page: 2) - + // Then - Verify(interactor, 2, .getAllCourses(filteredBy: .any, page: .any)) + XCTAssertEqual(interactor.getAllCoursesCallCount, 2) XCTAssertEqual(viewModel.nextPage, 3) } - + func testGetCoursesNoCachedDataError() async throws { // Given let viewModel = AllCoursesViewModel( @@ -153,18 +151,18 @@ final class AllCoursesViewModelTests: XCTestCase { analytics: analytics, storage: storage ) - - Given(interactor, .getAllCourses(filteredBy: .any, page: .any, willThrow: NoCachedDataError())) - + + interactor.getAllCoursesHandler = { _, _ in throw NoCachedDataError() } + // When await viewModel.getCourses(page: 1) - + // Then XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.noCachedData) XCTAssertTrue(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) } - + func testGetCoursesUnknownError() async throws { // Given let viewModel = AllCoursesViewModel( @@ -173,18 +171,18 @@ final class AllCoursesViewModelTests: XCTestCase { analytics: analytics, storage: storage ) - - Given(interactor, .getAllCourses(filteredBy: .any, page: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + + interactor.getAllCoursesHandler = { _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + // When await viewModel.getCourses(page: 1) - + // Then XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertTrue(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) } - + func testGetMyCoursesPagination() async { // Given let viewModel = AllCoursesViewModel( @@ -193,18 +191,18 @@ final class AllCoursesViewModelTests: XCTestCase { analytics: analytics, storage: storage ) - - Given(interactor, .getAllCourses(filteredBy: .any, page: .any, willReturn: mockEnrollment)) - + + interactor.getAllCoursesHandler = { _, _ in self.mockEnrollment } + // When await viewModel.getCourses(page: 1) await viewModel.getMyCoursesPagination(index: 0) await viewModel.getMyCoursesPagination(index: mockEnrollment.courses.count - 3) - + // Then - Verify(interactor, 2, .getAllCourses(filteredBy: .any, page: .any)) + XCTAssertEqual(interactor.getAllCoursesCallCount, 2) } - + func testTrackDashboardCourseClicked() { // Given let viewModel = AllCoursesViewModel( @@ -213,11 +211,11 @@ final class AllCoursesViewModelTests: XCTestCase { analytics: analytics, storage: storage ) - + // When viewModel.trackDashboardCourseClicked(courseID: "test-id", courseName: "Test Course") - + // Then - Verify(analytics, 1, .dashboardCourseClicked(courseID: .value("test-id"), courseName: .value("Test Course"))) + XCTAssertEqual(analytics.dashboardCourseClickedCallCount, 1) } } diff --git a/Dashboard/DashboardTests/Presentation/DashboardViewModelTests.swift b/Dashboard/DashboardTests/Presentation/DashboardViewModelTests.swift index a65038a05..c4c6cc5d0 100644 --- a/Dashboard/DashboardTests/Presentation/DashboardViewModelTests.swift +++ b/Dashboard/DashboardTests/Presentation/DashboardViewModelTests.swift @@ -2,10 +2,9 @@ // ListDashboardViewModelTests.swift // DashboardTests // -// Created by  Stepanok Ivan on 18.01.2023. +// Created by Stepanok Ivan on 18.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Dashboard @@ -14,7 +13,7 @@ import SwiftUI @MainActor final class ListDashboardViewModelTests: XCTestCase { - + func testGetMyCoursesSuccess() async throws { let interactor = DashboardInteractorProtocolMock() let connectivity = ConnectivityProtocolMock() @@ -25,7 +24,7 @@ final class ListDashboardViewModelTests: XCTestCase { analytics: analytics, storage: CoreStorageMock() ) - + let items = [ CourseItem(name: "Test", org: "org", @@ -59,18 +58,17 @@ final class ListDashboardViewModelTests: XCTestCase { progressPossible: 0) ] - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getEnrollments(page: .any, willReturn: items)) + connectivity.isInternetAvaliable = true + interactor.getEnrollmentsHandler = { _ in items } await viewModel.getMyCourses(page: 1) - Verify(interactor, 1, .getEnrollments(page: .value(1))) - + XCTAssertEqual(interactor.getEnrollmentsCallCount, 1) XCTAssertTrue(viewModel.courses == items) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.showError) } - + func testGetMyCoursesOfflineSuccess() async throws { let interactor = DashboardInteractorProtocolMock() let connectivity = ConnectivityProtocolMock() @@ -81,7 +79,7 @@ final class ListDashboardViewModelTests: XCTestCase { analytics: analytics, storage: CoreStorageMock() ) - + let items = [ CourseItem(name: "Test", org: "org", @@ -114,19 +112,18 @@ final class ListDashboardViewModelTests: XCTestCase { progressEarned: 0, progressPossible: 0) ] - - Given(connectivity, .isInternetAvaliable(getter: false)) - Given(interactor, .getEnrollmentsOffline(willReturn: items)) - + + connectivity.isInternetAvaliable = false + interactor.getEnrollmentsOfflineHandler = { items } + await viewModel.getMyCourses(page: 1) - - Verify(interactor, 1, .getEnrollmentsOffline()) - + + XCTAssertEqual(interactor.getEnrollmentsOfflineCallCount, 1) XCTAssertTrue(viewModel.courses == items) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.showError) } - + func testGetMyCoursesNoCacheError() async throws { let interactor = DashboardInteractorProtocolMock() let connectivity = ConnectivityProtocolMock() @@ -137,19 +134,18 @@ final class ListDashboardViewModelTests: XCTestCase { analytics: analytics, storage: CoreStorageMock() ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getEnrollments(page: .any, willThrow: NoCachedDataError()) ) - + + connectivity.isInternetAvaliable = true + interactor.getEnrollmentsHandler = { _ in throw NoCachedDataError() } + await viewModel.getMyCourses(page: 1) - - Verify(interactor, 1, .getEnrollments(page: .value(1))) - + + XCTAssertEqual(interactor.getEnrollmentsCallCount, 1) XCTAssertTrue(viewModel.courses.isEmpty) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.noCachedData) XCTAssertTrue(viewModel.showError) } - + func testGetMyCoursesUnknownError() async throws { let interactor = DashboardInteractorProtocolMock() let connectivity = ConnectivityProtocolMock() @@ -160,14 +156,13 @@ final class ListDashboardViewModelTests: XCTestCase { analytics: analytics, storage: CoreStorageMock() ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getEnrollments(page: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil)) ) - + + connectivity.isInternetAvaliable = true + interactor.getEnrollmentsHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + await viewModel.getMyCourses(page: 1) - - Verify(interactor, 1, .getEnrollments(page: .value(1))) - + + XCTAssertEqual(interactor.getEnrollmentsCallCount, 1) XCTAssertTrue(viewModel.courses.isEmpty) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertTrue(viewModel.showError) diff --git a/Dashboard/DashboardTests/Presentation/PrimaryCourseDashboardViewModelTests.swift b/Dashboard/DashboardTests/Presentation/PrimaryCourseDashboardViewModelTests.swift index 90f07790f..87393fd26 100644 --- a/Dashboard/DashboardTests/Presentation/PrimaryCourseDashboardViewModelTests.swift +++ b/Dashboard/DashboardTests/Presentation/PrimaryCourseDashboardViewModelTests.swift @@ -5,8 +5,6 @@ // Created by Ivan Stepanok on 30.10.2024. // - -import SwiftyMocky import XCTest @testable import Core @testable import Dashboard @@ -15,26 +13,26 @@ import SwiftUI @MainActor final class PrimaryCourseDashboardViewModelTests: XCTestCase { - + var interactor: DashboardInteractorProtocolMock! var connectivity: ConnectivityProtocolMock! var analytics: DashboardAnalyticsMock! var storage: CoreStorageMock! - var config: ConfigProtocolMock! + var config: ConfigMock! var router: DashboardRouterMock! - + override func setUp() { super.setUp() interactor = DashboardInteractorProtocolMock() connectivity = ConnectivityProtocolMock() analytics = DashboardAnalyticsMock() storage = CoreStorageMock() - config = ConfigProtocolMock() + config = ConfigMock() router = DashboardRouterMock() } - + let enrollment = PrimaryEnrollment( - primaryCourse: PrimaryCourse.init( + primaryCourse: PrimaryCourse( name: "Primary Course", org: "OpenEdX", courseID: "1", @@ -50,7 +48,7 @@ final class PrimaryCourseDashboardViewModelTests: XCTestCase { resumeTitle: nil ), courses: [ - CourseItem.init( + CourseItem( name: "Course", org: "OpenEdX", shortDescription: "short description", @@ -71,7 +69,7 @@ final class PrimaryCourseDashboardViewModelTests: XCTestCase { totalPages: 1, count: 1 ) - + func testGetEnrollmentsSuccess() async throws { // Given let viewModel = PrimaryCourseDashboardViewModel( @@ -82,21 +80,21 @@ final class PrimaryCourseDashboardViewModelTests: XCTestCase { storage: storage, router: router ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getPrimaryEnrollment(pageSize: .any, willReturn: enrollment)) - + + connectivity.isInternetAvaliable = true + interactor.getPrimaryEnrollmentHandler = { _ in self.enrollment } + // When await viewModel.getEnrollments() - + // Then - Verify(interactor, 1, .getPrimaryEnrollment(pageSize: .value(UIDevice.current.userInterfaceIdiom == .pad ? 7 : 5))) + XCTAssertEqual(interactor.getPrimaryEnrollmentCallCount, 1) XCTAssertEqual(viewModel.enrollments, enrollment) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) } - + func testGetEnrollmentsOfflineSuccess() async throws { // Given let viewModel = PrimaryCourseDashboardViewModel( @@ -107,21 +105,21 @@ final class PrimaryCourseDashboardViewModelTests: XCTestCase { storage: storage, router: router ) - - Given(connectivity, .isInternetAvaliable(getter: false)) - Given(interactor, .getPrimaryEnrollmentOffline(willReturn: enrollment)) - + + connectivity.isInternetAvaliable = false + interactor.getPrimaryEnrollmentOfflineHandler = { self.enrollment } + // When await viewModel.getEnrollments() - + // Then - Verify(interactor, 1, .getPrimaryEnrollmentOffline()) + XCTAssertEqual(interactor.getPrimaryEnrollmentOfflineCallCount, 1) XCTAssertEqual(viewModel.enrollments, enrollment) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) } - + func testGetEnrollmentsNoCacheError() async throws { // Given let viewModel = PrimaryCourseDashboardViewModel( @@ -132,21 +130,21 @@ final class PrimaryCourseDashboardViewModelTests: XCTestCase { storage: storage, router: router ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getPrimaryEnrollment(pageSize: .any, willThrow: NoCachedDataError())) - + + connectivity.isInternetAvaliable = true + interactor.getPrimaryEnrollmentHandler = { _ in throw NoCachedDataError() } + // When await viewModel.getEnrollments() - + // Then - Verify(interactor, 1, .getPrimaryEnrollment(pageSize: .value(UIDevice.current.userInterfaceIdiom == .pad ? 7 : 5))) + XCTAssertEqual(interactor.getPrimaryEnrollmentCallCount, 1) XCTAssertNil(viewModel.enrollments) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.noCachedData) XCTAssertTrue(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) } - + func testGetEnrollmentsUnknownError() async throws { // Given let viewModel = PrimaryCourseDashboardViewModel( @@ -157,21 +155,21 @@ final class PrimaryCourseDashboardViewModelTests: XCTestCase { storage: storage, router: router ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getPrimaryEnrollment(pageSize: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + + connectivity.isInternetAvaliable = true + interactor.getPrimaryEnrollmentHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + // When await viewModel.getEnrollments() - + // Then - Verify(interactor, 1, .getPrimaryEnrollment(pageSize: .value(UIDevice.current.userInterfaceIdiom == .pad ? 7 : 5))) + XCTAssertEqual(interactor.getPrimaryEnrollmentCallCount, 1) XCTAssertNil(viewModel.enrollments) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertTrue(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) } - + func testTrackDashboardCourseClicked() { // Given let viewModel = PrimaryCourseDashboardViewModel( @@ -182,17 +180,17 @@ final class PrimaryCourseDashboardViewModelTests: XCTestCase { storage: storage, router: router ) - + let courseID = "test-course-id" let courseName = "Test Course" - + // When viewModel.trackDashboardCourseClicked(courseID: courseID, courseName: courseName) - + // Then - Verify(analytics, 1, .dashboardCourseClicked(courseID: .value(courseID), courseName: .value(courseName))) + XCTAssertEqual(analytics.dashboardCourseClickedCallCount, 1) } - + func testNotificationCenterSubscriptions() async { // Given let viewModel = PrimaryCourseDashboardViewModel( @@ -203,20 +201,20 @@ final class PrimaryCourseDashboardViewModelTests: XCTestCase { storage: storage, router: router ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getPrimaryEnrollment(pageSize: .any, willReturn: enrollment)) - + + connectivity.isInternetAvaliable = true + interactor.getPrimaryEnrollmentHandler = { _ in self.enrollment } + // When NotificationCenter.default.post(name: .onCourseEnrolled, object: nil) NotificationCenter.default.post(name: .onblockCompletionRequested, object: nil) NotificationCenter.default.post(name: .refreshEnrollments, object: nil) - + // Wait a bit for async operations to complete try? await Task.sleep(nanoseconds: 100_000_000) - + // Then // Verify that getEnrollments was called multiple times due to notifications - Verify(interactor, .getPrimaryEnrollment(pageSize: .any)) + XCTAssertTrue(interactor.getPrimaryEnrollmentCallCount > 0) } } diff --git a/Dashboard/Mockfile b/Dashboard/Mockfile deleted file mode 100644 index 276791466..000000000 --- a/Dashboard/Mockfile +++ /dev/null @@ -1,18 +0,0 @@ -sourceryCommand: mint run krzysztofzablocki/Sourcery@2.1.2 sourcery -sourceryTemplate: ../MockTemplate.swifttemplate -unit.tests.mock: - sources: - include: - - ./../Core - - ./Dashboard - exclude: [] - output: ./DashboardTests/DashboardMock.generated.swift - targets: - - MyAppUnitTests - import: - - Core - - Dashboard - - Foundation - - SwiftUI - - Combine - - OEXFoundation \ No newline at end of file diff --git a/Discovery/Discovery.xcodeproj/project.pbxproj b/Discovery/Discovery.xcodeproj/project.pbxproj index 60ea0f9e1..5d5f494d5 100644 --- a/Discovery/Discovery.xcodeproj/project.pbxproj +++ b/Discovery/Discovery.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 022D048A2976D7E100E0059B /* DiscoveryViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022D04892976D7E100E0059B /* DiscoveryViewModelTests.swift */; }; 022D048B2976D7E100E0059B /* Discovery.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0727879928D34C03002E9142 /* Discovery.framework */; platformFilter = ios; }; - 022D04982976DA8A00E0059B /* DiscoveryMock.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022D04972976DA8A00E0059B /* DiscoveryMock.generated.swift */; }; 0283347728D499BC00C828FC /* DiscoveryInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0283347628D499BC00C828FC /* DiscoveryInteractor.swift */; }; 0284DBFC28D4856A00830893 /* DiscoveryEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0284DBFB28D4856A00830893 /* DiscoveryEndpoint.swift */; }; 0284DC0328D4922900830893 /* DiscoveryRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0284DC0228D4922900830893 /* DiscoveryRepository.swift */; }; @@ -28,6 +27,7 @@ 1402A0CA2B61012F00A0A00B /* ProgramWebviewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1402A0C82B61012F00A0A00B /* ProgramWebviewViewModel.swift */; }; 63C6E9CBBF5E33B8B9B4DFEC /* Pods_App_Discovery_DiscoveryUnitTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 780FC373E1D479E58870BD85 /* Pods_App_Discovery_DiscoveryUnitTests.framework */; }; 9F47BCC672941A9854404EC7 /* Pods_App_Discovery.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 919E55130969D91EF03C4C0B /* Pods_App_Discovery.framework */; }; + A5B469172F29DFCC002A4ECA /* DiscoveryMocks.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B469152F29DFCC002A4ECA /* DiscoveryMocks.generated.swift */; }; CE7CAF312CC155FD00E0AC9D /* OEXFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CE7CAF302CC155FD00E0AC9D /* OEXFoundation */; }; CEB1E26A2CC14E7900921517 /* OEXFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CEB1E2692CC14E7900921517 /* OEXFoundation */; }; CFC8494C299A66080055E497 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = CFC8494E299A66080055E497 /* Localizable.stringsdict */; }; @@ -73,7 +73,6 @@ /* Begin PBXFileReference section */ 022D04872976D7E100E0059B /* DiscoveryUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DiscoveryUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 022D04892976D7E100E0059B /* DiscoveryViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoveryViewModelTests.swift; sourceTree = ""; }; - 022D04972976DA8A00E0059B /* DiscoveryMock.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DiscoveryMock.generated.swift; path = DiscoveryTests/DiscoveryMock.generated.swift; sourceTree = SOURCE_ROOT; }; 0283347628D499BC00C828FC /* DiscoveryInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoveryInteractor.swift; sourceTree = ""; }; 0284DBFB28D4856A00830893 /* DiscoveryEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoveryEndpoint.swift; sourceTree = ""; }; 0284DC0228D4922900830893 /* DiscoveryRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoveryRepository.swift; sourceTree = ""; }; @@ -106,6 +105,7 @@ 83FB998DD9C5B57B61B88170 /* Pods-App-Discovery-DiscoveryUnitTests.releasestage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Discovery-DiscoveryUnitTests.releasestage.xcconfig"; path = "Target Support Files/Pods-App-Discovery-DiscoveryUnitTests/Pods-App-Discovery-DiscoveryUnitTests.releasestage.xcconfig"; sourceTree = ""; }; 919E55130969D91EF03C4C0B /* Pods_App_Discovery.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App_Discovery.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9F968F74AD7F4B5F6E5A6084 /* Pods-App-Discovery-DiscoveryUnitTests.debugdev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Discovery-DiscoveryUnitTests.debugdev.xcconfig"; path = "Target Support Files/Pods-App-Discovery-DiscoveryUnitTests/Pods-App-Discovery-DiscoveryUnitTests.debugdev.xcconfig"; sourceTree = ""; }; + A5B469152F29DFCC002A4ECA /* DiscoveryMocks.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoveryMocks.generated.swift; sourceTree = ""; }; AAC0D83F5D34491E9FABCABC /* Pods-App-Discovery-DiscoveryUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Discovery-DiscoveryUnitTests.debug.xcconfig"; path = "Target Support Files/Pods-App-Discovery-DiscoveryUnitTests/Pods-App-Discovery-DiscoveryUnitTests.debug.xcconfig"; sourceTree = ""; }; CFC8494D299A66080055E497 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; CFC8494F299BE52C0055E497 /* SearchViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewModelTests.swift; sourceTree = ""; }; @@ -166,8 +166,8 @@ 022D04882976D7E100E0059B /* DiscoveryTests */ = { isa = PBXGroup; children = ( + A5B469162F29DFCC002A4ECA /* Generated */, 0766DFD1299AD97300EBEF6A /* Presentation */, - 022D04972976DA8A00E0059B /* DiscoveryMock.generated.swift */, ); path = DiscoveryTests; sourceTree = ""; @@ -320,6 +320,14 @@ path = ../Pods; sourceTree = ""; }; + A5B469162F29DFCC002A4ECA /* Generated */ = { + isa = PBXGroup; + children = ( + A5B469152F29DFCC002A4ECA /* DiscoveryMocks.generated.swift */, + ); + path = Generated; + sourceTree = ""; + }; E0B9F6952B4D57F800168366 /* NativeDiscovery */ = { isa = PBXGroup; children = ( @@ -374,7 +382,6 @@ 022D04832976D7E100E0059B /* Sources */, 022D04842976D7E100E0059B /* Frameworks */, 022D04852976D7E100E0059B /* Resources */, - 7A53F60C849FA0F910D22A82 /* [CP] Copy Pods Resources */, CE7CAF332CC155FE00E0AC9D /* Embed Frameworks */, ); buildRules = ( @@ -510,23 +517,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 7A53F60C849FA0F910D22A82 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Discovery-DiscoveryUnitTests/Pods-App-Discovery-DiscoveryUnitTests-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Discovery-DiscoveryUnitTests/Pods-App-Discovery-DiscoveryUnitTests-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App-Discovery-DiscoveryUnitTests/Pods-App-Discovery-DiscoveryUnitTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; CD2104C69B21D34605FA0B30 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -557,7 +547,7 @@ buildActionMask = 2147483647; files = ( 022D048A2976D7E100E0059B /* DiscoveryViewModelTests.swift in Sources */, - 022D04982976DA8A00E0059B /* DiscoveryMock.generated.swift in Sources */, + A5B469172F29DFCC002A4ECA /* DiscoveryMocks.generated.swift in Sources */, E0B9F6AB2B4E718F00168366 /* CourseDetailsViewModelTests.swift in Sources */, CFC84950299BE52C0055E497 /* SearchViewModelTests.swift in Sources */, ); diff --git a/Discovery/Discovery/Data/DiscoveryRepository.swift b/Discovery/Discovery/Data/DiscoveryRepository.swift index 9ce20c9c3..866001239 100644 --- a/Discovery/Discovery/Data/DiscoveryRepository.swift +++ b/Discovery/Discovery/Data/DiscoveryRepository.swift @@ -11,6 +11,7 @@ import OEXFoundation import CoreData import Alamofire +/// @mockable public protocol DiscoveryRepositoryProtocol: Sendable { func getDiscovery(page: Int) async throws -> [CourseItem] func searchCourses(page: Int, searchTerm: String) async throws -> [CourseItem] @@ -82,7 +83,7 @@ public actor DiscoveryRepository: DiscoveryRepositoryProtocol { // Mark - For testing and SwiftUI preview #if DEBUG -final class DiscoveryRepositoryMock: DiscoveryRepositoryProtocol { +final class DiscoveryRepositoryPreviewMock: DiscoveryRepositoryProtocol { public func getCourseDetails(courseID: String) async throws -> CourseDetails { return CourseDetails( diff --git a/Discovery/Discovery/Domain/DiscoveryInteractor.swift b/Discovery/Discovery/Domain/DiscoveryInteractor.swift index 480ba05b4..cd77552a5 100644 --- a/Discovery/Discovery/Domain/DiscoveryInteractor.swift +++ b/Discovery/Discovery/Domain/DiscoveryInteractor.swift @@ -8,7 +8,7 @@ import Foundation import Core -//sourcery: AutoMockable +/// @mockable public protocol DiscoveryInteractorProtocol: Sendable { func discovery(page: Int) async throws -> [CourseItem] func discoveryOffline() async throws -> [CourseItem] @@ -54,6 +54,6 @@ public actor DiscoveryInteractor: DiscoveryInteractorProtocol { // Mark - For testing and SwiftUI preview #if DEBUG public extension DiscoveryInteractor { - static let mock = DiscoveryInteractor(repository: DiscoveryRepositoryMock()) + static let mock = DiscoveryInteractor(repository: DiscoveryRepositoryPreviewMock()) } #endif diff --git a/Discovery/Discovery/Presentation/DiscoveryAnalytics.swift b/Discovery/Discovery/Presentation/DiscoveryAnalytics.swift index d5c722bd3..1786b86c5 100644 --- a/Discovery/Discovery/Presentation/DiscoveryAnalytics.swift +++ b/Discovery/Discovery/Presentation/DiscoveryAnalytics.swift @@ -9,7 +9,7 @@ import Foundation import Core import OEXFoundation -//sourcery: AutoMockable +/// @mockable public protocol DiscoveryAnalytics { func discoverySearchBarClicked() func discoveryCoursesSearch(label: String, coursesCount: Int) @@ -23,7 +23,7 @@ public protocol DiscoveryAnalytics { } #if DEBUG -class DiscoveryAnalyticsMock: DiscoveryAnalytics { +class DiscoveryAnalyticsPreviewMock: DiscoveryAnalytics { public func discoverySearchBarClicked() {} public func discoveryCoursesSearch(label: String, coursesCount: Int) {} public func discoveryCourseClicked(courseID: String, courseName: String) {} diff --git a/Discovery/Discovery/Presentation/DiscoveryRouter.swift b/Discovery/Discovery/Presentation/DiscoveryRouter.swift index 8ba09740a..1f2369b86 100644 --- a/Discovery/Discovery/Presentation/DiscoveryRouter.swift +++ b/Discovery/Discovery/Presentation/DiscoveryRouter.swift @@ -8,6 +8,7 @@ import Foundation import Core +/// @mockable @MainActor public protocol DiscoveryRouter: BaseRouter { func showCourseDetais(courseID: String, title: String) @@ -40,7 +41,7 @@ public protocol DiscoveryRouter: BaseRouter { // Mark - For testing and SwiftUI preview #if DEBUG -public class DiscoveryRouterMock: BaseRouterMock, DiscoveryRouter { +public class DiscoveryRouterPreviewMock: BaseRouterMock, DiscoveryRouter { public override init() {} diff --git a/Discovery/Discovery/Presentation/NativeDiscovery/CourseDetailsView.swift b/Discovery/Discovery/Presentation/NativeDiscovery/CourseDetailsView.swift index fe1c32657..94b6b79d4 100644 --- a/Discovery/Discovery/Presentation/NativeDiscovery/CourseDetailsView.swift +++ b/Discovery/Discovery/Presentation/NativeDiscovery/CourseDetailsView.swift @@ -435,8 +435,8 @@ struct CourseDetailsView_Previews: PreviewProvider { static var previews: some View { let vm = CourseDetailsViewModel( interactor: DiscoveryInteractor.mock, - router: DiscoveryRouterMock(), - analytics: DiscoveryAnalyticsMock(), + router: DiscoveryRouterPreviewMock(), + analytics: DiscoveryAnalyticsPreviewMock(), config: ConfigMock(), cssInjector: CSSInjectorMock(), connectivity: Connectivity(config: ConfigMock()), diff --git a/Discovery/Discovery/Presentation/NativeDiscovery/DiscoveryView.swift b/Discovery/Discovery/Presentation/NativeDiscovery/DiscoveryView.swift index cafe26adb..fd5a3a398 100644 --- a/Discovery/Discovery/Presentation/NativeDiscovery/DiscoveryView.swift +++ b/Discovery/Discovery/Presentation/NativeDiscovery/DiscoveryView.swift @@ -208,13 +208,13 @@ public struct DiscoveryView: View { #if DEBUG struct DiscoveryView_Previews: PreviewProvider { static var previews: some View { - let vm = DiscoveryViewModel(router: DiscoveryRouterMock(), + let vm = DiscoveryViewModel(router: DiscoveryRouterPreviewMock(), config: ConfigMock(), interactor: DiscoveryInteractor.mock, connectivity: Connectivity(config: ConfigMock()), - analytics: DiscoveryAnalyticsMock(), + analytics: DiscoveryAnalyticsPreviewMock(), storage: CoreStorageMock()) - let router = DiscoveryRouterMock() + let router = DiscoveryRouterPreviewMock() DiscoveryView(viewModel: vm, router: router) .preferredColorScheme(.light) diff --git a/Discovery/Discovery/Presentation/NativeDiscovery/SearchView.swift b/Discovery/Discovery/Presentation/NativeDiscovery/SearchView.swift index 7c565bfad..9aa8f5702 100644 --- a/Discovery/Discovery/Presentation/NativeDiscovery/SearchView.swift +++ b/Discovery/Discovery/Presentation/NativeDiscovery/SearchView.swift @@ -219,12 +219,12 @@ public struct SearchView: View { #if DEBUG struct SearchView_Previews: PreviewProvider { static var previews: some View { - let router = DiscoveryRouterMock() + let router = DiscoveryRouterPreviewMock() let vm = SearchViewModel( interactor: DiscoveryInteractor.mock, connectivity: Connectivity(config: ConfigMock()), router: router, - analytics: DiscoveryAnalyticsMock(), + analytics: DiscoveryAnalyticsPreviewMock(), storage: CoreStorageMock(), debounce: .searchDebounce ) diff --git a/Discovery/Discovery/Presentation/UpdateViews/UpdateRecommendedView.swift b/Discovery/Discovery/Presentation/UpdateViews/UpdateRecommendedView.swift index f017d4ac4..2b886512f 100644 --- a/Discovery/Discovery/Presentation/UpdateViews/UpdateRecommendedView.swift +++ b/Discovery/Discovery/Presentation/UpdateViews/UpdateRecommendedView.swift @@ -78,7 +78,7 @@ public struct UpdateRecommendedView: View { struct UpdateRecommendedView_Previews: PreviewProvider { static var previews: some View { UpdateRecommendedView( - router: DiscoveryRouterMock(), + router: DiscoveryRouterPreviewMock(), config: ConfigMock() ) } diff --git a/Discovery/Discovery/Presentation/UpdateViews/UpdateRequiredView.swift b/Discovery/Discovery/Presentation/UpdateViews/UpdateRequiredView.swift index 2c3c53a79..59553fae7 100644 --- a/Discovery/Discovery/Presentation/UpdateViews/UpdateRequiredView.swift +++ b/Discovery/Discovery/Presentation/UpdateViews/UpdateRequiredView.swift @@ -68,7 +68,7 @@ public struct UpdateRequiredView: View { struct UpdateRequiredView_Previews: PreviewProvider { static var previews: some View { UpdateRequiredView( - router: DiscoveryRouterMock(), + router: DiscoveryRouterPreviewMock(), config: ConfigMock() ) .loadFonts() diff --git a/Discovery/Discovery/Presentation/WebPrograms/ProgramWebviewView.swift b/Discovery/Discovery/Presentation/WebPrograms/ProgramWebviewView.swift index dbfc60403..7ceb6f74d 100644 --- a/Discovery/Discovery/Presentation/WebPrograms/ProgramWebviewView.swift +++ b/Discovery/Discovery/Presentation/WebPrograms/ProgramWebviewView.swift @@ -136,14 +136,14 @@ struct ProgramWebviewView_Previews: PreviewProvider { static var previews: some View { ProgramWebviewView( viewModel: ProgramWebviewViewModel( - router: DiscoveryRouterMock(), + router: DiscoveryRouterPreviewMock(), config: ConfigMock(), interactor: DiscoveryInteractor.mock, connectivity: Connectivity(config: ConfigMock()), - analytics: DiscoveryAnalyticsMock(), + analytics: DiscoveryAnalyticsPreviewMock(), authInteractor: AuthInteractor.mock ), - router: DiscoveryRouterMock(), + router: DiscoveryRouterPreviewMock(), viewType: .program, pathID: "" ) diff --git a/Discovery/DiscoveryTests/DiscoveryMock.generated.swift b/Discovery/DiscoveryTests/DiscoveryMock.generated.swift deleted file mode 100644 index 67602250f..000000000 --- a/Discovery/DiscoveryTests/DiscoveryMock.generated.swift +++ /dev/null @@ -1,5295 +0,0 @@ -// Generated using Sourcery 2.1.2 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT - - -// Generated with SwiftyMocky 4.2.0 -// Required Sourcery: 1.8.0 - - -import SwiftyMocky -import XCTest -import Core -import Discovery -import Foundation -import SwiftUI -import Combine -import OEXFoundation - - -// MARK: - AuthInteractorProtocol - -open class AuthInteractorProtocolMock: AuthInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - @discardableResult - open func login(username: String, password: String) throws -> User { - addInvocation(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) - let perform = methodPerformValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) as? (String, String) -> Void - perform?(`username`, `password`) - var __value: User - do { - __value = try methodReturnValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(username: String, password: String). Use given") - Failure("Stub return value not specified for login(username: String, password: String). Use given") - } catch { - throw error - } - return __value - } - - @discardableResult - open func login(externalToken: String, backend: String) throws -> User { - addInvocation(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) - let perform = methodPerformValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) as? (String, String) -> Void - perform?(`externalToken`, `backend`) - var __value: User - do { - __value = try methodReturnValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - Failure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - } catch { - throw error - } - return __value - } - - open func login(ssoToken: String) throws -> User { - addInvocation(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) - let perform = methodPerformValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) as? (String) -> Void - perform?(`ssoToken`) - var __value: User - do { - __value = try methodReturnValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(ssoToken: String). Use given") - Failure("Stub return value not specified for login(ssoToken: String). Use given") - } catch { - throw error - } - return __value - } - - open func resetPassword(email: String) throws -> ResetPassword { - addInvocation(.m_resetPassword__email_email(Parameter.value(`email`))) - let perform = methodPerformValue(.m_resetPassword__email_email(Parameter.value(`email`))) as? (String) -> Void - perform?(`email`) - var __value: ResetPassword - do { - __value = try methodReturnValue(.m_resetPassword__email_email(Parameter.value(`email`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for resetPassword(email: String). Use given") - Failure("Stub return value not specified for resetPassword(email: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCookies(force: Bool) throws { - addInvocation(.m_getCookies__force_force(Parameter.value(`force`))) - let perform = methodPerformValue(.m_getCookies__force_force(Parameter.value(`force`))) as? (Bool) -> Void - perform?(`force`) - do { - _ = try methodReturnValue(.m_getCookies__force_force(Parameter.value(`force`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getRegistrationFields() throws -> [PickerFields] { - addInvocation(.m_getRegistrationFields) - let perform = methodPerformValue(.m_getRegistrationFields) as? () -> Void - perform?() - var __value: [PickerFields] - do { - __value = try methodReturnValue(.m_getRegistrationFields).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getRegistrationFields(). Use given") - Failure("Stub return value not specified for getRegistrationFields(). Use given") - } catch { - throw error - } - return __value - } - - open func registerUser(fields: [String: String], isSocial: Bool) throws -> User { - addInvocation(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) - let perform = methodPerformValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) as? ([String: String], Bool) -> Void - perform?(`fields`, `isSocial`) - var __value: User - do { - __value = try methodReturnValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - Failure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - } catch { - throw error - } - return __value - } - - open func validateRegistrationFields(fields: [String: String]) throws -> [String: String] { - addInvocation(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) - let perform = methodPerformValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) as? ([String: String]) -> Void - perform?(`fields`) - var __value: [String: String] - do { - __value = try methodReturnValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - Failure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_login__username_usernamepassword_password(Parameter, Parameter) - case m_login__externalToken_externalTokenbackend_backend(Parameter, Parameter) - case m_login__ssoToken_ssoToken(Parameter) - case m_resetPassword__email_email(Parameter) - case m_getCookies__force_force(Parameter) - case m_getRegistrationFields - case m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>, Parameter) - case m_validateRegistrationFields__fields_fields(Parameter<[String: String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_login__username_usernamepassword_password(let lhsUsername, let lhsPassword), .m_login__username_usernamepassword_password(let rhsUsername, let rhsPassword)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsername, rhs: rhsUsername, with: matcher), lhsUsername, rhsUsername, "username")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPassword, rhs: rhsPassword, with: matcher), lhsPassword, rhsPassword, "password")) - return Matcher.ComparisonResult(results) - - case (.m_login__externalToken_externalTokenbackend_backend(let lhsExternaltoken, let lhsBackend), .m_login__externalToken_externalTokenbackend_backend(let rhsExternaltoken, let rhsBackend)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsExternaltoken, rhs: rhsExternaltoken, with: matcher), lhsExternaltoken, rhsExternaltoken, "externalToken")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBackend, rhs: rhsBackend, with: matcher), lhsBackend, rhsBackend, "backend")) - return Matcher.ComparisonResult(results) - - case (.m_login__ssoToken_ssoToken(let lhsSsotoken), .m_login__ssoToken_ssoToken(let rhsSsotoken)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSsotoken, rhs: rhsSsotoken, with: matcher), lhsSsotoken, rhsSsotoken, "ssoToken")) - return Matcher.ComparisonResult(results) - - case (.m_resetPassword__email_email(let lhsEmail), .m_resetPassword__email_email(let rhsEmail)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEmail, rhs: rhsEmail, with: matcher), lhsEmail, rhsEmail, "email")) - return Matcher.ComparisonResult(results) - - case (.m_getCookies__force_force(let lhsForce), .m_getCookies__force_force(let rhsForce)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsForce, rhs: rhsForce, with: matcher), lhsForce, rhsForce, "force")) - return Matcher.ComparisonResult(results) - - case (.m_getRegistrationFields, .m_getRegistrationFields): return .match - - case (.m_registerUser__fields_fieldsisSocial_isSocial(let lhsFields, let lhsIssocial), .m_registerUser__fields_fieldsisSocial_isSocial(let rhsFields, let rhsIssocial)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIssocial, rhs: rhsIssocial, with: matcher), lhsIssocial, rhsIssocial, "isSocial")) - return Matcher.ComparisonResult(results) - - case (.m_validateRegistrationFields__fields_fields(let lhsFields), .m_validateRegistrationFields__fields_fields(let rhsFields)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_login__username_usernamepassword_password(p0, p1): return p0.intValue + p1.intValue - case let .m_login__externalToken_externalTokenbackend_backend(p0, p1): return p0.intValue + p1.intValue - case let .m_login__ssoToken_ssoToken(p0): return p0.intValue - case let .m_resetPassword__email_email(p0): return p0.intValue - case let .m_getCookies__force_force(p0): return p0.intValue - case .m_getRegistrationFields: return 0 - case let .m_registerUser__fields_fieldsisSocial_isSocial(p0, p1): return p0.intValue + p1.intValue - case let .m_validateRegistrationFields__fields_fields(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_login__username_usernamepassword_password: return ".login(username:password:)" - case .m_login__externalToken_externalTokenbackend_backend: return ".login(externalToken:backend:)" - case .m_login__ssoToken_ssoToken: return ".login(ssoToken:)" - case .m_resetPassword__email_email: return ".resetPassword(email:)" - case .m_getCookies__force_force: return ".getCookies(force:)" - case .m_getRegistrationFields: return ".getRegistrationFields()" - case .m_registerUser__fields_fieldsisSocial_isSocial: return ".registerUser(fields:isSocial:)" - case .m_validateRegistrationFields__fields_fields: return ".validateRegistrationFields(fields:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - @discardableResult - public static func login(username: Parameter, password: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func login(ssoToken: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func resetPassword(email: Parameter, willReturn: ResetPassword...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getRegistrationFields(willReturn: [PickerFields]...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willReturn: [String: String]...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func login(ssoToken: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func login(ssoToken: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func resetPassword(email: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resetPassword(email: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (ResetPassword).self) - willProduce(stubber) - return given - } - public static func getCookies(force: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCookies(force: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func getRegistrationFields(willThrow: Error...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getRegistrationFields(willProduce: (StubberThrows<[PickerFields]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([PickerFields]).self) - willProduce(stubber) - return given - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willProduce: (StubberThrows<[String: String]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([String: String]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - @discardableResult - public static func login(username: Parameter, password: Parameter) -> Verify { return Verify(method: .m_login__username_usernamepassword_password(`username`, `password`))} - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter) -> Verify { return Verify(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`))} - public static func login(ssoToken: Parameter) -> Verify { return Verify(method: .m_login__ssoToken_ssoToken(`ssoToken`))} - public static func resetPassword(email: Parameter) -> Verify { return Verify(method: .m_resetPassword__email_email(`email`))} - public static func getCookies(force: Parameter) -> Verify { return Verify(method: .m_getCookies__force_force(`force`))} - public static func getRegistrationFields() -> Verify { return Verify(method: .m_getRegistrationFields)} - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter) -> Verify { return Verify(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`))} - public static func validateRegistrationFields(fields: Parameter<[String: String]>) -> Verify { return Verify(method: .m_validateRegistrationFields__fields_fields(`fields`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - @discardableResult - public static func login(username: Parameter, password: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__username_usernamepassword_password(`username`, `password`), performs: perform) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), performs: perform) - } - public static func login(ssoToken: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_login__ssoToken_ssoToken(`ssoToken`), performs: perform) - } - public static func resetPassword(email: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_resetPassword__email_email(`email`), performs: perform) - } - public static func getCookies(force: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_getCookies__force_force(`force`), performs: perform) - } - public static func getRegistrationFields(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getRegistrationFields, performs: perform) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, perform: @escaping ([String: String], Bool) -> Void) -> Perform { - return Perform(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), performs: perform) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, perform: @escaping ([String: String]) -> Void) -> Perform { - return Perform(method: .m_validateRegistrationFields__fields_fields(`fields`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - BaseRouter -@MainActor -open class BaseRouterMock: BaseRouter, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func backToRoot(animated: Bool) { - addInvocation(.m_backToRoot__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_backToRoot__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func back(animated: Bool) { - addInvocation(.m_back__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_back__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func backWithFade() { - addInvocation(.m_backWithFade) - let perform = methodPerformValue(.m_backWithFade) as? () -> Void - perform?() - } - - open func dismiss(animated: Bool) { - addInvocation(.m_dismiss__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_dismiss__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func removeLastView(controllers: Int) { - addInvocation(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) - let perform = methodPerformValue(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) as? (Int) -> Void - perform?(`controllers`) - } - - open func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { - addInvocation(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) - let perform = methodPerformValue(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) as? (LogistrationSourceScreen, PostLoginData?) -> Void - perform?(`sourceScreen`, `postLoginData`) - } - - open func showStartupScreen() { - addInvocation(.m_showStartupScreen) - let perform = methodPerformValue(.m_showStartupScreen) as? () -> Void - perform?() - } - - open func showLoginScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showForgotPasswordScreen() { - addInvocation(.m_showForgotPasswordScreen) - let perform = methodPerformValue(.m_showForgotPasswordScreen) as? () -> Void - perform?() - } - - open func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) as? (String?, LogistrationSourceScreen) -> Void - perform?(`searchQuery`, `sourceScreen`) - } - - open func showWebBrowser(title: String, url: URL) { - addInvocation(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) - let perform = methodPerformValue(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) as? (String, URL) -> Void - perform?(`title`, `url`) - } - - open func showSSOWebBrowser(title: String) { - addInvocation(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) - let perform = methodPerformValue(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) as? (String) -> Void - perform?(`title`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) as? (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void - perform?(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) as? (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void - perform?(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { - addInvocation(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) as? (UIModalTransitionStyle, any View, (() -> Void)?) -> Void - perform?(`transitionStyle`, `view`, `completion`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { - addInvocation(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) as? (UIModalTransitionStyle, Bool, () -> any View) -> Void - perform?(`transitionStyle`, `animated`, `content`) - } - - - fileprivate enum MethodType { - case m_backToRoot__animated_animated(Parameter) - case m_back__animated_animated(Parameter) - case m_backWithFade - case m_dismiss__animated_animated(Parameter) - case m_removeLastView__controllers_controllers(Parameter) - case m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter, Parameter) - case m_showStartupScreen - case m_showLoginScreen__sourceScreen_sourceScreen(Parameter) - case m_showRegisterScreen__sourceScreen_sourceScreen(Parameter) - case m_showForgotPasswordScreen - case m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter, Parameter) - case m_showWebBrowser__title_titleurl_url(Parameter, Parameter) - case m_showSSOWebBrowser__title_title(Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter<() -> Void>) - case m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter, Parameter, Parameter<(() -> Void)?>) - case m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter, Parameter, Parameter<() -> any View>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_backToRoot__animated_animated(let lhsAnimated), .m_backToRoot__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_back__animated_animated(let lhsAnimated), .m_back__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_backWithFade, .m_backWithFade): return .match - - case (.m_dismiss__animated_animated(let lhsAnimated), .m_dismiss__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_removeLastView__controllers_controllers(let lhsControllers), .m_removeLastView__controllers_controllers(let rhsControllers)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsControllers, rhs: rhsControllers, with: matcher), lhsControllers, rhsControllers, "controllers")) - return Matcher.ComparisonResult(results) - - case (.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let lhsSourcescreen, let lhsPostlogindata), .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let rhsSourcescreen, let rhsPostlogindata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPostlogindata, rhs: rhsPostlogindata, with: matcher), lhsPostlogindata, rhsPostlogindata, "postLoginData")) - return Matcher.ComparisonResult(results) - - case (.m_showStartupScreen, .m_showStartupScreen): return .match - - case (.m_showLoginScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showLoginScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showRegisterScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showRegisterScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showForgotPasswordScreen, .m_showForgotPasswordScreen): return .match - - case (.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let lhsSearchquery, let lhsSourcescreen), .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let rhsSearchquery, let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchquery, rhs: rhsSearchquery, with: matcher), lhsSearchquery, rhsSearchquery, "searchQuery")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showWebBrowser__title_titleurl_url(let lhsTitle, let lhsUrl), .m_showWebBrowser__title_titleurl_url(let rhsTitle, let rhsUrl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - return Matcher.ComparisonResult(results) - - case (.m_showSSOWebBrowser__title_title(let lhsTitle), .m_showSSOWebBrowser__title_title(let rhsTitle)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let lhsAlerttitle, let lhsAlertmessage, let lhsPositiveaction, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsType), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let rhsAlerttitle, let rhsAlertmessage, let rhsPositiveaction, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPositiveaction, rhs: rhsPositiveaction, with: matcher), lhsPositiveaction, rhsPositiveaction, "positiveAction")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let lhsAlerttitle, let lhsAlertmessage, let lhsNextsectionname, let lhsAction, let lhsImage, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsNextsectiontapped), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let rhsAlerttitle, let rhsAlertmessage, let rhsNextsectionname, let rhsAction, let rhsImage, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsNextsectiontapped)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectionname, rhs: rhsNextsectionname, with: matcher), lhsNextsectionname, rhsNextsectionname, "nextSectionName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsImage, rhs: rhsImage, with: matcher), lhsImage, rhsImage, "image")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectiontapped, rhs: rhsNextsectiontapped, with: matcher), lhsNextsectiontapped, rhsNextsectiontapped, "nextSectionTapped")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let lhsTransitionstyle, let lhsView, let lhsCompletion), .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let rhsTransitionstyle, let rhsView, let rhsCompletion)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsView, rhs: rhsView, with: matcher), lhsView, rhsView, "view")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCompletion, rhs: rhsCompletion, with: matcher), lhsCompletion, rhsCompletion, "completion")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let lhsTransitionstyle, let lhsAnimated, let lhsContent), .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let rhsTransitionstyle, let rhsAnimated, let rhsContent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsContent, rhs: rhsContent, with: matcher), lhsContent, rhsContent, "content")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_backToRoot__animated_animated(p0): return p0.intValue - case let .m_back__animated_animated(p0): return p0.intValue - case .m_backWithFade: return 0 - case let .m_dismiss__animated_animated(p0): return p0.intValue - case let .m_removeLastView__controllers_controllers(p0): return p0.intValue - case let .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(p0, p1): return p0.intValue + p1.intValue - case .m_showStartupScreen: return 0 - case let .m_showLoginScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case let .m_showRegisterScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case .m_showForgotPasswordScreen: return 0 - case let .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(p0, p1): return p0.intValue + p1.intValue - case let .m_showWebBrowser__title_titleurl_url(p0, p1): return p0.intValue + p1.intValue - case let .m_showSSOWebBrowser__title_title(p0): return p0.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(p0, p1, p2, p3, p4, p5, p6, p7): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue + p7.intValue - case let .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_backToRoot__animated_animated: return ".backToRoot(animated:)" - case .m_back__animated_animated: return ".back(animated:)" - case .m_backWithFade: return ".backWithFade()" - case .m_dismiss__animated_animated: return ".dismiss(animated:)" - case .m_removeLastView__controllers_controllers: return ".removeLastView(controllers:)" - case .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData: return ".showMainOrWhatsNewScreen(sourceScreen:postLoginData:)" - case .m_showStartupScreen: return ".showStartupScreen()" - case .m_showLoginScreen__sourceScreen_sourceScreen: return ".showLoginScreen(sourceScreen:)" - case .m_showRegisterScreen__sourceScreen_sourceScreen: return ".showRegisterScreen(sourceScreen:)" - case .m_showForgotPasswordScreen: return ".showForgotPasswordScreen()" - case .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen: return ".showDiscoveryScreen(searchQuery:sourceScreen:)" - case .m_showWebBrowser__title_titleurl_url: return ".showWebBrowser(title:url:)" - case .m_showSSOWebBrowser__title_title: return ".showSSOWebBrowser(title:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type: return ".presentAlert(alertTitle:alertMessage:positiveAction:onCloseTapped:firstButtonTapped:type:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped: return ".presentAlert(alertTitle:alertMessage:nextSectionName:action:image:onCloseTapped:firstButtonTapped:nextSectionTapped:)" - case .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion: return ".presentView(transitionStyle:view:completion:)" - case .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content: return ".presentView(transitionStyle:animated:content:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func backToRoot(animated: Parameter) -> Verify { return Verify(method: .m_backToRoot__animated_animated(`animated`))} - public static func back(animated: Parameter) -> Verify { return Verify(method: .m_back__animated_animated(`animated`))} - public static func backWithFade() -> Verify { return Verify(method: .m_backWithFade)} - public static func dismiss(animated: Parameter) -> Verify { return Verify(method: .m_dismiss__animated_animated(`animated`))} - public static func removeLastView(controllers: Parameter) -> Verify { return Verify(method: .m_removeLastView__controllers_controllers(`controllers`))} - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter) -> Verify { return Verify(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`))} - public static func showStartupScreen() -> Verify { return Verify(method: .m_showStartupScreen)} - public static func showLoginScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showRegisterScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showForgotPasswordScreen() -> Verify { return Verify(method: .m_showForgotPasswordScreen)} - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter) -> Verify { return Verify(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`))} - public static func showWebBrowser(title: Parameter, url: Parameter) -> Verify { return Verify(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`))} - public static func showSSOWebBrowser(title: Parameter) -> Verify { return Verify(method: .m_showSSOWebBrowser__title_title(`title`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`))} - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`))} - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func backToRoot(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_backToRoot__animated_animated(`animated`), performs: perform) - } - public static func back(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_back__animated_animated(`animated`), performs: perform) - } - public static func backWithFade(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_backWithFade, performs: perform) - } - public static func dismiss(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_dismiss__animated_animated(`animated`), performs: perform) - } - public static func removeLastView(controllers: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_removeLastView__controllers_controllers(`controllers`), performs: perform) - } - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter, perform: @escaping (LogistrationSourceScreen, PostLoginData?) -> Void) -> Perform { - return Perform(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`), performs: perform) - } - public static func showStartupScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showStartupScreen, performs: perform) - } - public static func showLoginScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showRegisterScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showForgotPasswordScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showForgotPasswordScreen, performs: perform) - } - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter, perform: @escaping (String?, LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`), performs: perform) - } - public static func showWebBrowser(title: Parameter, url: Parameter, perform: @escaping (String, URL) -> Void) -> Perform { - return Perform(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`), performs: perform) - } - public static func showSSOWebBrowser(title: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showSSOWebBrowser__title_title(`title`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter, perform: @escaping (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>, perform: @escaping (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>, perform: @escaping (UIModalTransitionStyle, any View, (() -> Void)?) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>, perform: @escaping (UIModalTransitionStyle, Bool, () -> any View) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CalendarManagerProtocol -@MainActor -open class CalendarManagerProtocolMock: CalendarManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func createCalendarIfNeeded() { - addInvocation(.m_createCalendarIfNeeded) - let perform = methodPerformValue(.m_createCalendarIfNeeded) as? () -> Void - perform?() - } - - open func filterCoursesBySelected(fetchedCourses: [CourseForSync]) -> [CourseForSync] { - addInvocation(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) - let perform = methodPerformValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) as? ([CourseForSync]) -> Void - perform?(`fetchedCourses`) - var __value: [CourseForSync] - do { - __value = try methodReturnValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))).casted() - } catch { - onFatalFailure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - Failure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - } - return __value - } - - open func removeOldCalendar() { - addInvocation(.m_removeOldCalendar) - let perform = methodPerformValue(.m_removeOldCalendar) as? () -> Void - perform?() - } - - open func removeOutdatedEvents(courseID: String) { - addInvocation(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - } - - open func syncCourse(courseID: String, courseName: String, dates: CourseDates) { - addInvocation(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) - let perform = methodPerformValue(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) as? (String, String, CourseDates) -> Void - perform?(`courseID`, `courseName`, `dates`) - } - - open func requestAccess() -> Bool { - addInvocation(.m_requestAccess) - let perform = methodPerformValue(.m_requestAccess) as? () -> Void - perform?() - var __value: Bool - do { - __value = try methodReturnValue(.m_requestAccess).casted() - } catch { - onFatalFailure("Stub return value not specified for requestAccess(). Use given") - Failure("Stub return value not specified for requestAccess(). Use given") - } - return __value - } - - open func courseStatus(courseID: String) -> SyncStatus { - addInvocation(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: SyncStatus - do { - __value = try methodReturnValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for courseStatus(courseID: String). Use given") - Failure("Stub return value not specified for courseStatus(courseID: String). Use given") - } - return __value - } - - open func clearAllData(removeCalendar: Bool) { - addInvocation(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) - let perform = methodPerformValue(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) as? (Bool) -> Void - perform?(`removeCalendar`) - } - - open func isDatesChanged(courseID: String, checksum: String) -> Bool { - addInvocation(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) - let perform = methodPerformValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) as? (String, String) -> Void - perform?(`courseID`, `checksum`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - Failure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - } - return __value - } - - - fileprivate enum MethodType { - case m_createCalendarIfNeeded - case m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>) - case m_removeOldCalendar - case m_removeOutdatedEvents__courseID_courseID(Parameter) - case m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter, Parameter, Parameter) - case m_requestAccess - case m_courseStatus__courseID_courseID(Parameter) - case m_clearAllData__removeCalendar_removeCalendar(Parameter) - case m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_createCalendarIfNeeded, .m_createCalendarIfNeeded): return .match - - case (.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let lhsFetchedcourses), .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let rhsFetchedcourses)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFetchedcourses, rhs: rhsFetchedcourses, with: matcher), lhsFetchedcourses, rhsFetchedcourses, "fetchedCourses")) - return Matcher.ComparisonResult(results) - - case (.m_removeOldCalendar, .m_removeOldCalendar): return .match - - case (.m_removeOutdatedEvents__courseID_courseID(let lhsCourseid), .m_removeOutdatedEvents__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let lhsCourseid, let lhsCoursename, let lhsDates), .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let rhsCourseid, let rhsCoursename, let rhsDates)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDates, rhs: rhsDates, with: matcher), lhsDates, rhsDates, "dates")) - return Matcher.ComparisonResult(results) - - case (.m_requestAccess, .m_requestAccess): return .match - - case (.m_courseStatus__courseID_courseID(let lhsCourseid), .m_courseStatus__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_clearAllData__removeCalendar_removeCalendar(let lhsRemovecalendar), .m_clearAllData__removeCalendar_removeCalendar(let rhsRemovecalendar)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRemovecalendar, rhs: rhsRemovecalendar, with: matcher), lhsRemovecalendar, rhsRemovecalendar, "removeCalendar")) - return Matcher.ComparisonResult(results) - - case (.m_isDatesChanged__courseID_courseIDchecksum_checksum(let lhsCourseid, let lhsChecksum), .m_isDatesChanged__courseID_courseIDchecksum_checksum(let rhsCourseid, let rhsChecksum)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsChecksum, rhs: rhsChecksum, with: matcher), lhsChecksum, rhsChecksum, "checksum")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_createCalendarIfNeeded: return 0 - case let .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(p0): return p0.intValue - case .m_removeOldCalendar: return 0 - case let .m_removeOutdatedEvents__courseID_courseID(p0): return p0.intValue - case let .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case .m_requestAccess: return 0 - case let .m_courseStatus__courseID_courseID(p0): return p0.intValue - case let .m_clearAllData__removeCalendar_removeCalendar(p0): return p0.intValue - case let .m_isDatesChanged__courseID_courseIDchecksum_checksum(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_createCalendarIfNeeded: return ".createCalendarIfNeeded()" - case .m_filterCoursesBySelected__fetchedCourses_fetchedCourses: return ".filterCoursesBySelected(fetchedCourses:)" - case .m_removeOldCalendar: return ".removeOldCalendar()" - case .m_removeOutdatedEvents__courseID_courseID: return ".removeOutdatedEvents(courseID:)" - case .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates: return ".syncCourse(courseID:courseName:dates:)" - case .m_requestAccess: return ".requestAccess()" - case .m_courseStatus__courseID_courseID: return ".courseStatus(courseID:)" - case .m_clearAllData__removeCalendar_removeCalendar: return ".clearAllData(removeCalendar:)" - case .m_isDatesChanged__courseID_courseIDchecksum_checksum: return ".isDatesChanged(courseID:checksum:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willReturn: [CourseForSync]...) -> MethodStub { - return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func requestAccess(willReturn: Bool...) -> MethodStub { - return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func courseStatus(courseID: Parameter, willReturn: SyncStatus...) -> MethodStub { - return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willProduce: (Stubber<[CourseForSync]>) -> Void) -> MethodStub { - let willReturn: [[CourseForSync]] = [] - let given: Given = { return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([CourseForSync]).self) - willProduce(stubber) - return given - } - public static func requestAccess(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func courseStatus(courseID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [SyncStatus] = [] - let given: Given = { return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (SyncStatus).self) - willProduce(stubber) - return given - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func createCalendarIfNeeded() -> Verify { return Verify(method: .m_createCalendarIfNeeded)} - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>) -> Verify { return Verify(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`))} - public static func removeOldCalendar() -> Verify { return Verify(method: .m_removeOldCalendar)} - public static func removeOutdatedEvents(courseID: Parameter) -> Verify { return Verify(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`))} - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter) -> Verify { return Verify(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`))} - public static func requestAccess() -> Verify { return Verify(method: .m_requestAccess)} - public static func courseStatus(courseID: Parameter) -> Verify { return Verify(method: .m_courseStatus__courseID_courseID(`courseID`))} - public static func clearAllData(removeCalendar: Parameter) -> Verify { return Verify(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`))} - public static func isDatesChanged(courseID: Parameter, checksum: Parameter) -> Verify { return Verify(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func createCalendarIfNeeded(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_createCalendarIfNeeded, performs: perform) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, perform: @escaping ([CourseForSync]) -> Void) -> Perform { - return Perform(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), performs: perform) - } - public static func removeOldCalendar(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeOldCalendar, performs: perform) - } - public static func removeOutdatedEvents(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`), performs: perform) - } - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter, perform: @escaping (String, String, CourseDates) -> Void) -> Perform { - return Perform(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`), performs: perform) - } - public static func requestAccess(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_requestAccess, performs: perform) - } - public static func courseStatus(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_courseStatus__courseID_courseID(`courseID`), performs: perform) - } - public static func clearAllData(removeCalendar: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`), performs: perform) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConfigProtocol - -open class ConfigProtocolMock: ConfigProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var baseURL: URL { - get { invocations.append(.p_baseURL_get); return __p_baseURL ?? givenGetterValue(.p_baseURL_get, "ConfigProtocolMock - stub value for baseURL was not defined") } - } - private var __p_baseURL: (URL)? - - public var baseSSOURL: URL { - get { invocations.append(.p_baseSSOURL_get); return __p_baseSSOURL ?? givenGetterValue(.p_baseSSOURL_get, "ConfigProtocolMock - stub value for baseSSOURL was not defined") } - } - private var __p_baseSSOURL: (URL)? - - public var ssoFinishedURL: URL { - get { invocations.append(.p_ssoFinishedURL_get); return __p_ssoFinishedURL ?? givenGetterValue(.p_ssoFinishedURL_get, "ConfigProtocolMock - stub value for ssoFinishedURL was not defined") } - } - private var __p_ssoFinishedURL: (URL)? - - public var ssoButtonTitle: [String: Any] { - get { invocations.append(.p_ssoButtonTitle_get); return __p_ssoButtonTitle ?? givenGetterValue(.p_ssoButtonTitle_get, "ConfigProtocolMock - stub value for ssoButtonTitle was not defined") } - } - private var __p_ssoButtonTitle: ([String: Any])? - - public var oAuthClientId: String { - get { invocations.append(.p_oAuthClientId_get); return __p_oAuthClientId ?? givenGetterValue(.p_oAuthClientId_get, "ConfigProtocolMock - stub value for oAuthClientId was not defined") } - } - private var __p_oAuthClientId: (String)? - - public var tokenType: TokenType { - get { invocations.append(.p_tokenType_get); return __p_tokenType ?? givenGetterValue(.p_tokenType_get, "ConfigProtocolMock - stub value for tokenType was not defined") } - } - private var __p_tokenType: (TokenType)? - - public var feedbackEmail: String { - get { invocations.append(.p_feedbackEmail_get); return __p_feedbackEmail ?? givenGetterValue(.p_feedbackEmail_get, "ConfigProtocolMock - stub value for feedbackEmail was not defined") } - } - private var __p_feedbackEmail: (String)? - - public var appStoreLink: String { - get { invocations.append(.p_appStoreLink_get); return __p_appStoreLink ?? givenGetterValue(.p_appStoreLink_get, "ConfigProtocolMock - stub value for appStoreLink was not defined") } - } - private var __p_appStoreLink: (String)? - - public var faq: URL? { - get { invocations.append(.p_faq_get); return __p_faq ?? optionalGivenGetterValue(.p_faq_get, "ConfigProtocolMock - stub value for faq was not defined") } - } - private var __p_faq: (URL)? - - public var platformName: String { - get { invocations.append(.p_platformName_get); return __p_platformName ?? givenGetterValue(.p_platformName_get, "ConfigProtocolMock - stub value for platformName was not defined") } - } - private var __p_platformName: (String)? - - public var agreement: AgreementConfig { - get { invocations.append(.p_agreement_get); return __p_agreement ?? givenGetterValue(.p_agreement_get, "ConfigProtocolMock - stub value for agreement was not defined") } - } - private var __p_agreement: (AgreementConfig)? - - public var firebase: FirebaseConfig { - get { invocations.append(.p_firebase_get); return __p_firebase ?? givenGetterValue(.p_firebase_get, "ConfigProtocolMock - stub value for firebase was not defined") } - } - private var __p_firebase: (FirebaseConfig)? - - public var facebook: FacebookConfig { - get { invocations.append(.p_facebook_get); return __p_facebook ?? givenGetterValue(.p_facebook_get, "ConfigProtocolMock - stub value for facebook was not defined") } - } - private var __p_facebook: (FacebookConfig)? - - public var microsoft: MicrosoftConfig { - get { invocations.append(.p_microsoft_get); return __p_microsoft ?? givenGetterValue(.p_microsoft_get, "ConfigProtocolMock - stub value for microsoft was not defined") } - } - private var __p_microsoft: (MicrosoftConfig)? - - public var google: GoogleConfig { - get { invocations.append(.p_google_get); return __p_google ?? givenGetterValue(.p_google_get, "ConfigProtocolMock - stub value for google was not defined") } - } - private var __p_google: (GoogleConfig)? - - public var appleSignIn: AppleSignInConfig { - get { invocations.append(.p_appleSignIn_get); return __p_appleSignIn ?? givenGetterValue(.p_appleSignIn_get, "ConfigProtocolMock - stub value for appleSignIn was not defined") } - } - private var __p_appleSignIn: (AppleSignInConfig)? - - public var features: FeaturesConfig { - get { invocations.append(.p_features_get); return __p_features ?? givenGetterValue(.p_features_get, "ConfigProtocolMock - stub value for features was not defined") } - } - private var __p_features: (FeaturesConfig)? - - public var theme: ThemeConfig { - get { invocations.append(.p_theme_get); return __p_theme ?? givenGetterValue(.p_theme_get, "ConfigProtocolMock - stub value for theme was not defined") } - } - private var __p_theme: (ThemeConfig)? - - public var uiComponents: UIComponentsConfig { - get { invocations.append(.p_uiComponents_get); return __p_uiComponents ?? givenGetterValue(.p_uiComponents_get, "ConfigProtocolMock - stub value for uiComponents was not defined") } - } - private var __p_uiComponents: (UIComponentsConfig)? - - public var discovery: DiscoveryConfig { - get { invocations.append(.p_discovery_get); return __p_discovery ?? givenGetterValue(.p_discovery_get, "ConfigProtocolMock - stub value for discovery was not defined") } - } - private var __p_discovery: (DiscoveryConfig)? - - public var dashboard: DashboardConfig { - get { invocations.append(.p_dashboard_get); return __p_dashboard ?? givenGetterValue(.p_dashboard_get, "ConfigProtocolMock - stub value for dashboard was not defined") } - } - private var __p_dashboard: (DashboardConfig)? - - public var braze: BrazeConfig { - get { invocations.append(.p_braze_get); return __p_braze ?? givenGetterValue(.p_braze_get, "ConfigProtocolMock - stub value for braze was not defined") } - } - private var __p_braze: (BrazeConfig)? - - public var branch: BranchConfig { - get { invocations.append(.p_branch_get); return __p_branch ?? givenGetterValue(.p_branch_get, "ConfigProtocolMock - stub value for branch was not defined") } - } - private var __p_branch: (BranchConfig)? - - public var program: DiscoveryConfig { - get { invocations.append(.p_program_get); return __p_program ?? givenGetterValue(.p_program_get, "ConfigProtocolMock - stub value for program was not defined") } - } - private var __p_program: (DiscoveryConfig)? - - public var experimentalFeatures: ExperimentalFeaturesConfig { - get { invocations.append(.p_experimentalFeatures_get); return __p_experimentalFeatures ?? givenGetterValue(.p_experimentalFeatures_get, "ConfigProtocolMock - stub value for experimentalFeatures was not defined") } - } - private var __p_experimentalFeatures: (ExperimentalFeaturesConfig)? - - public var URIScheme: String { - get { invocations.append(.p_URIScheme_get); return __p_URIScheme ?? givenGetterValue(.p_URIScheme_get, "ConfigProtocolMock - stub value for URIScheme was not defined") } - } - private var __p_URIScheme: (String)? - - - - - - - fileprivate enum MethodType { - case p_baseURL_get - case p_baseSSOURL_get - case p_ssoFinishedURL_get - case p_ssoButtonTitle_get - case p_oAuthClientId_get - case p_tokenType_get - case p_feedbackEmail_get - case p_appStoreLink_get - case p_faq_get - case p_platformName_get - case p_agreement_get - case p_firebase_get - case p_facebook_get - case p_microsoft_get - case p_google_get - case p_appleSignIn_get - case p_features_get - case p_theme_get - case p_uiComponents_get - case p_discovery_get - case p_dashboard_get - case p_braze_get - case p_branch_get - case p_program_get - case p_experimentalFeatures_get - case p_URIScheme_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_baseURL_get,.p_baseURL_get): return Matcher.ComparisonResult.match - case (.p_baseSSOURL_get,.p_baseSSOURL_get): return Matcher.ComparisonResult.match - case (.p_ssoFinishedURL_get,.p_ssoFinishedURL_get): return Matcher.ComparisonResult.match - case (.p_ssoButtonTitle_get,.p_ssoButtonTitle_get): return Matcher.ComparisonResult.match - case (.p_oAuthClientId_get,.p_oAuthClientId_get): return Matcher.ComparisonResult.match - case (.p_tokenType_get,.p_tokenType_get): return Matcher.ComparisonResult.match - case (.p_feedbackEmail_get,.p_feedbackEmail_get): return Matcher.ComparisonResult.match - case (.p_appStoreLink_get,.p_appStoreLink_get): return Matcher.ComparisonResult.match - case (.p_faq_get,.p_faq_get): return Matcher.ComparisonResult.match - case (.p_platformName_get,.p_platformName_get): return Matcher.ComparisonResult.match - case (.p_agreement_get,.p_agreement_get): return Matcher.ComparisonResult.match - case (.p_firebase_get,.p_firebase_get): return Matcher.ComparisonResult.match - case (.p_facebook_get,.p_facebook_get): return Matcher.ComparisonResult.match - case (.p_microsoft_get,.p_microsoft_get): return Matcher.ComparisonResult.match - case (.p_google_get,.p_google_get): return Matcher.ComparisonResult.match - case (.p_appleSignIn_get,.p_appleSignIn_get): return Matcher.ComparisonResult.match - case (.p_features_get,.p_features_get): return Matcher.ComparisonResult.match - case (.p_theme_get,.p_theme_get): return Matcher.ComparisonResult.match - case (.p_uiComponents_get,.p_uiComponents_get): return Matcher.ComparisonResult.match - case (.p_discovery_get,.p_discovery_get): return Matcher.ComparisonResult.match - case (.p_dashboard_get,.p_dashboard_get): return Matcher.ComparisonResult.match - case (.p_braze_get,.p_braze_get): return Matcher.ComparisonResult.match - case (.p_branch_get,.p_branch_get): return Matcher.ComparisonResult.match - case (.p_program_get,.p_program_get): return Matcher.ComparisonResult.match - case (.p_experimentalFeatures_get,.p_experimentalFeatures_get): return Matcher.ComparisonResult.match - case (.p_URIScheme_get,.p_URIScheme_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_baseURL_get: return 0 - case .p_baseSSOURL_get: return 0 - case .p_ssoFinishedURL_get: return 0 - case .p_ssoButtonTitle_get: return 0 - case .p_oAuthClientId_get: return 0 - case .p_tokenType_get: return 0 - case .p_feedbackEmail_get: return 0 - case .p_appStoreLink_get: return 0 - case .p_faq_get: return 0 - case .p_platformName_get: return 0 - case .p_agreement_get: return 0 - case .p_firebase_get: return 0 - case .p_facebook_get: return 0 - case .p_microsoft_get: return 0 - case .p_google_get: return 0 - case .p_appleSignIn_get: return 0 - case .p_features_get: return 0 - case .p_theme_get: return 0 - case .p_uiComponents_get: return 0 - case .p_discovery_get: return 0 - case .p_dashboard_get: return 0 - case .p_braze_get: return 0 - case .p_branch_get: return 0 - case .p_program_get: return 0 - case .p_experimentalFeatures_get: return 0 - case .p_URIScheme_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_baseURL_get: return "[get] .baseURL" - case .p_baseSSOURL_get: return "[get] .baseSSOURL" - case .p_ssoFinishedURL_get: return "[get] .ssoFinishedURL" - case .p_ssoButtonTitle_get: return "[get] .ssoButtonTitle" - case .p_oAuthClientId_get: return "[get] .oAuthClientId" - case .p_tokenType_get: return "[get] .tokenType" - case .p_feedbackEmail_get: return "[get] .feedbackEmail" - case .p_appStoreLink_get: return "[get] .appStoreLink" - case .p_faq_get: return "[get] .faq" - case .p_platformName_get: return "[get] .platformName" - case .p_agreement_get: return "[get] .agreement" - case .p_firebase_get: return "[get] .firebase" - case .p_facebook_get: return "[get] .facebook" - case .p_microsoft_get: return "[get] .microsoft" - case .p_google_get: return "[get] .google" - case .p_appleSignIn_get: return "[get] .appleSignIn" - case .p_features_get: return "[get] .features" - case .p_theme_get: return "[get] .theme" - case .p_uiComponents_get: return "[get] .uiComponents" - case .p_discovery_get: return "[get] .discovery" - case .p_dashboard_get: return "[get] .dashboard" - case .p_braze_get: return "[get] .braze" - case .p_branch_get: return "[get] .branch" - case .p_program_get: return "[get] .program" - case .p_experimentalFeatures_get: return "[get] .experimentalFeatures" - case .p_URIScheme_get: return "[get] .URIScheme" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func baseURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func baseSSOURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseSSOURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoFinishedURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_ssoFinishedURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoButtonTitle(getter defaultValue: [String: Any]...) -> PropertyStub { - return Given(method: .p_ssoButtonTitle_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func oAuthClientId(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_oAuthClientId_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func tokenType(getter defaultValue: TokenType...) -> PropertyStub { - return Given(method: .p_tokenType_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func feedbackEmail(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_feedbackEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appStoreLink(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_appStoreLink_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func faq(getter defaultValue: URL?...) -> PropertyStub { - return Given(method: .p_faq_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func platformName(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_platformName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func agreement(getter defaultValue: AgreementConfig...) -> PropertyStub { - return Given(method: .p_agreement_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func firebase(getter defaultValue: FirebaseConfig...) -> PropertyStub { - return Given(method: .p_firebase_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func facebook(getter defaultValue: FacebookConfig...) -> PropertyStub { - return Given(method: .p_facebook_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func microsoft(getter defaultValue: MicrosoftConfig...) -> PropertyStub { - return Given(method: .p_microsoft_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func google(getter defaultValue: GoogleConfig...) -> PropertyStub { - return Given(method: .p_google_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignIn(getter defaultValue: AppleSignInConfig...) -> PropertyStub { - return Given(method: .p_appleSignIn_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func features(getter defaultValue: FeaturesConfig...) -> PropertyStub { - return Given(method: .p_features_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func theme(getter defaultValue: ThemeConfig...) -> PropertyStub { - return Given(method: .p_theme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func uiComponents(getter defaultValue: UIComponentsConfig...) -> PropertyStub { - return Given(method: .p_uiComponents_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func discovery(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_discovery_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func dashboard(getter defaultValue: DashboardConfig...) -> PropertyStub { - return Given(method: .p_dashboard_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func braze(getter defaultValue: BrazeConfig...) -> PropertyStub { - return Given(method: .p_braze_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func branch(getter defaultValue: BranchConfig...) -> PropertyStub { - return Given(method: .p_branch_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func program(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_program_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func experimentalFeatures(getter defaultValue: ExperimentalFeaturesConfig...) -> PropertyStub { - return Given(method: .p_experimentalFeatures_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func URIScheme(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_URIScheme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var baseURL: Verify { return Verify(method: .p_baseURL_get) } - public static var baseSSOURL: Verify { return Verify(method: .p_baseSSOURL_get) } - public static var ssoFinishedURL: Verify { return Verify(method: .p_ssoFinishedURL_get) } - public static var ssoButtonTitle: Verify { return Verify(method: .p_ssoButtonTitle_get) } - public static var oAuthClientId: Verify { return Verify(method: .p_oAuthClientId_get) } - public static var tokenType: Verify { return Verify(method: .p_tokenType_get) } - public static var feedbackEmail: Verify { return Verify(method: .p_feedbackEmail_get) } - public static var appStoreLink: Verify { return Verify(method: .p_appStoreLink_get) } - public static var faq: Verify { return Verify(method: .p_faq_get) } - public static var platformName: Verify { return Verify(method: .p_platformName_get) } - public static var agreement: Verify { return Verify(method: .p_agreement_get) } - public static var firebase: Verify { return Verify(method: .p_firebase_get) } - public static var facebook: Verify { return Verify(method: .p_facebook_get) } - public static var microsoft: Verify { return Verify(method: .p_microsoft_get) } - public static var google: Verify { return Verify(method: .p_google_get) } - public static var appleSignIn: Verify { return Verify(method: .p_appleSignIn_get) } - public static var features: Verify { return Verify(method: .p_features_get) } - public static var theme: Verify { return Verify(method: .p_theme_get) } - public static var uiComponents: Verify { return Verify(method: .p_uiComponents_get) } - public static var discovery: Verify { return Verify(method: .p_discovery_get) } - public static var dashboard: Verify { return Verify(method: .p_dashboard_get) } - public static var braze: Verify { return Verify(method: .p_braze_get) } - public static var branch: Verify { return Verify(method: .p_branch_get) } - public static var program: Verify { return Verify(method: .p_program_get) } - public static var experimentalFeatures: Verify { return Verify(method: .p_experimentalFeatures_get) } - public static var URIScheme: Verify { return Verify(method: .p_URIScheme_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConnectivityProtocol -@MainActor -open class ConnectivityProtocolMock: ConnectivityProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var isInternetAvaliable: Bool { - get { invocations.append(.p_isInternetAvaliable_get); return __p_isInternetAvaliable ?? givenGetterValue(.p_isInternetAvaliable_get, "ConnectivityProtocolMock - stub value for isInternetAvaliable was not defined") } - } - private var __p_isInternetAvaliable: (Bool)? - - public var isMobileData: Bool { - get { invocations.append(.p_isMobileData_get); return __p_isMobileData ?? givenGetterValue(.p_isMobileData_get, "ConnectivityProtocolMock - stub value for isMobileData was not defined") } - } - private var __p_isMobileData: (Bool)? - - public var internetReachableSubject: CurrentValueSubject { - get { invocations.append(.p_internetReachableSubject_get); return __p_internetReachableSubject ?? givenGetterValue(.p_internetReachableSubject_get, "ConnectivityProtocolMock - stub value for internetReachableSubject was not defined") } - } - private var __p_internetReachableSubject: (CurrentValueSubject)? - - - - - - - fileprivate enum MethodType { - case p_isInternetAvaliable_get - case p_isMobileData_get - case p_internetReachableSubject_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_isInternetAvaliable_get,.p_isInternetAvaliable_get): return Matcher.ComparisonResult.match - case (.p_isMobileData_get,.p_isMobileData_get): return Matcher.ComparisonResult.match - case (.p_internetReachableSubject_get,.p_internetReachableSubject_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_isInternetAvaliable_get: return 0 - case .p_isMobileData_get: return 0 - case .p_internetReachableSubject_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_isInternetAvaliable_get: return "[get] .isInternetAvaliable" - case .p_isMobileData_get: return "[get] .isMobileData" - case .p_internetReachableSubject_get: return "[get] .internetReachableSubject" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func isInternetAvaliable(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isInternetAvaliable_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func isMobileData(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isMobileData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func internetReachableSubject(getter defaultValue: CurrentValueSubject...) -> PropertyStub { - return Given(method: .p_internetReachableSubject_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var isInternetAvaliable: Verify { return Verify(method: .p_isInternetAvaliable_get) } - public static var isMobileData: Verify { return Verify(method: .p_isMobileData_get) } - public static var internetReachableSubject: Verify { return Verify(method: .p_internetReachableSubject_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreAnalytics - -open class CoreAnalyticsMock: CoreAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { - addInvocation(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) - let perform = methodPerformValue(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) as? (AnalyticsEvent, EventBIValue, String?, Int?) -> Void - perform?(`event`, `biValue`, `action`, `rating`) - } - - open func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { - addInvocation(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) - let perform = methodPerformValue(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) as? (AnalyticsEvent, EventBIValue, String, String) -> Void - perform?(`event`, `bivalue`, `value`, `oldValue`) - } - - open func trackEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackScreenEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackScreenEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - - fileprivate enum MethodType { - case m_trackEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter, Parameter, Parameter, Parameter) - case m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter, Parameter, Parameter, Parameter) - case m_trackEvent__event(Parameter) - case m_trackEvent__eventbiValue_biValue(Parameter, Parameter) - case m_trackScreenEvent__event(Parameter) - case m_trackScreenEvent__eventbiValue_biValue(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_trackEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackScreenEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_appreview__eventbiValue_biValueaction_actionrating_rating(let lhsEvent, let lhsBivalue, let lhsAction, let lhsRating), .m_appreview__eventbiValue_biValueaction_actionrating_rating(let rhsEvent, let rhsBivalue, let rhsAction, let rhsRating)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRating, rhs: rhsRating, with: matcher), lhsRating, rhsRating, "rating")) - return Matcher.ComparisonResult(results) - - case (.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let lhsEvent, let lhsBivalue, let lhsValue, let lhsOldvalue), .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let rhsEvent, let rhsBivalue, let rhsValue, let rhsOldvalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "bivalue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsValue, rhs: rhsValue, with: matcher), lhsValue, rhsValue, "value")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOldvalue, rhs: rhsOldvalue, with: matcher), lhsOldvalue, rhsOldvalue, "oldValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__event(let lhsEvent), .m_trackEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__event(let lhsEvent), .m_trackScreenEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackScreenEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_trackEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_trackScreenEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_appreview__eventbiValue_biValueaction_actionrating_rating(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_trackEvent__event(p0): return p0.intValue - case let .m_trackEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__event(p0): return p0.intValue - case let .m_trackScreenEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_trackEvent__eventparameters_parameters: return ".trackEvent(_:parameters:)" - case .m_trackEvent__eventbiValue_biValueparameters_parameters: return ".trackEvent(_:biValue:parameters:)" - case .m_trackScreenEvent__eventparameters_parameters: return ".trackScreenEvent(_:parameters:)" - case .m_trackScreenEvent__eventbiValue_biValueparameters_parameters: return ".trackScreenEvent(_:biValue:parameters:)" - case .m_appreview__eventbiValue_biValueaction_actionrating_rating: return ".appreview(_:biValue:action:rating:)" - case .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue: return ".videoQualityChanged(_:bivalue:value:oldValue:)" - case .m_trackEvent__event: return ".trackEvent(_:)" - case .m_trackEvent__eventbiValue_biValue: return ".trackEvent(_:biValue:)" - case .m_trackScreenEvent__event: return ".trackScreenEvent(_:)" - case .m_trackScreenEvent__eventbiValue_biValue: return ".trackScreenEvent(_:biValue:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter) -> Verify { return Verify(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`))} - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter) -> Verify { return Verify(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`))} - public static func trackEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackEvent__event(`event`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`))} - public static func trackScreenEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__event(`event`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String?, Int?) -> Void) -> Perform { - return Perform(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`), performs: perform) - } - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String, String) -> Void) -> Perform { - return Perform(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`), performs: perform) - } - public static func trackEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackEvent__event(`event`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__event(`event`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CorePersistenceProtocol - -open class CorePersistenceProtocolMock: CorePersistenceProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func set(userId: Int) { - addInvocation(.m_set__userId_userId(Parameter.value(`userId`))) - let perform = methodPerformValue(.m_set__userId_userId(Parameter.value(`userId`))) as? (Int) -> Void - perform?(`userId`) - } - - open func getUserID() -> Int? { - addInvocation(.m_getUserID) - let perform = methodPerformValue(.m_getUserID) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getUserID).casted() - } catch { - // do nothing - } - return __value - } - - @MainActor - open func publisher() throws -> AnyPublisher { - addInvocation(.m_publisher) - let perform = methodPerformValue(.m_publisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_publisher).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for publisher(). Use given") - Failure("Stub return value not specified for publisher(). Use given") - } catch { - throw error - } - return __value - } - - open func addToDownloadQueue(tasks: [DownloadDataTask]) { - addInvocation(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) as? ([DownloadDataTask]) -> Void - perform?(`tasks`) - } - - open func saveOfflineProgress(progress: OfflineProgress) { - addInvocation(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) - let perform = methodPerformValue(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) as? (OfflineProgress) -> Void - perform?(`progress`) - } - - open func loadProgress(for blockID: String) -> OfflineProgress? { - addInvocation(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - var __value: OfflineProgress? = nil - do { - __value = try methodReturnValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))).casted() - } catch { - // do nothing - } - return __value - } - - open func loadAllOfflineProgress() -> [OfflineProgress] { - addInvocation(.m_loadAllOfflineProgress) - let perform = methodPerformValue(.m_loadAllOfflineProgress) as? () -> Void - perform?() - var __value: [OfflineProgress] - do { - __value = try methodReturnValue(.m_loadAllOfflineProgress).casted() - } catch { - onFatalFailure("Stub return value not specified for loadAllOfflineProgress(). Use given") - Failure("Stub return value not specified for loadAllOfflineProgress(). Use given") - } - return __value - } - - open func deleteProgress(for blockID: String) { - addInvocation(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - } - - open func deleteAllProgress() { - addInvocation(.m_deleteAllProgress) - let perform = methodPerformValue(.m_deleteAllProgress) as? () -> Void - perform?() - } - - open func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { - addInvocation(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) as? ([CourseBlock], DownloadQuality) -> Void - perform?(`blocks`, `downloadQuality`) - } - - open func updateTask(task: DownloadDataTask) { - addInvocation(.m_updateTask__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_updateTask__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - } - - open func downloadDataTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getDownloadDataTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasks) - let perform = methodPerformValue(.m_getDownloadDataTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasks(). Use given") - Failure("Stub return value not specified for getDownloadDataTasks(). Use given") - } - return __value - } - - open func getDownloadDataTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func deleteDownloadDataTasks(ids: [String]) { - addInvocation(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) - let perform = methodPerformValue(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) as? ([String]) -> Void - perform?(`ids`) - } - - - fileprivate enum MethodType { - case m_set__userId_userId(Parameter) - case m_getUserID - case m_publisher - case m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>) - case m_saveOfflineProgress__progress_progress(Parameter) - case m_loadProgress__for_blockID(Parameter) - case m_loadAllOfflineProgress - case m_deleteProgress__for_blockID(Parameter) - case m_deleteAllProgress - case m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>, Parameter) - case m_updateTask__task_task(Parameter) - case m_downloadDataTask__for_blockId(Parameter) - case m_getDownloadDataTasks - case m_getDownloadDataTasksForCourse__courseId(Parameter) - case m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_set__userId_userId(let lhsUserid), .m_set__userId_userId(let rhsUserid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUserid, rhs: rhsUserid, with: matcher), lhsUserid, rhsUserid, "userId")) - return Matcher.ComparisonResult(results) - - case (.m_getUserID, .m_getUserID): return .match - - case (.m_publisher, .m_publisher): return .match - - case (.m_addToDownloadQueue__tasks_tasks(let lhsTasks), .m_addToDownloadQueue__tasks_tasks(let rhsTasks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTasks, rhs: rhsTasks, with: matcher), lhsTasks, rhsTasks, "tasks")) - return Matcher.ComparisonResult(results) - - case (.m_saveOfflineProgress__progress_progress(let lhsProgress), .m_saveOfflineProgress__progress_progress(let rhsProgress)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsProgress, rhs: rhsProgress, with: matcher), lhsProgress, rhsProgress, "progress")) - return Matcher.ComparisonResult(results) - - case (.m_loadProgress__for_blockID(let lhsBlockid), .m_loadProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_loadAllOfflineProgress, .m_loadAllOfflineProgress): return .match - - case (.m_deleteProgress__for_blockID(let lhsBlockid), .m_deleteProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_deleteAllProgress, .m_deleteAllProgress): return .match - - case (.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let lhsBlocks, let lhsDownloadquality), .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let rhsBlocks, let rhsDownloadquality)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadquality, rhs: rhsDownloadquality, with: matcher), lhsDownloadquality, rhsDownloadquality, "downloadQuality")) - return Matcher.ComparisonResult(results) - - case (.m_updateTask__task_task(let lhsTask), .m_updateTask__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_downloadDataTask__for_blockId(let lhsBlockid), .m_downloadDataTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadDataTasks, .m_getDownloadDataTasks): return .match - - case (.m_getDownloadDataTasksForCourse__courseId(let lhsCourseid), .m_getDownloadDataTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_deleteDownloadDataTasks__ids_ids(let lhsIds), .m_deleteDownloadDataTasks__ids_ids(let rhsIds)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIds, rhs: rhsIds, with: matcher), lhsIds, rhsIds, "ids")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_set__userId_userId(p0): return p0.intValue - case .m_getUserID: return 0 - case .m_publisher: return 0 - case let .m_addToDownloadQueue__tasks_tasks(p0): return p0.intValue - case let .m_saveOfflineProgress__progress_progress(p0): return p0.intValue - case let .m_loadProgress__for_blockID(p0): return p0.intValue - case .m_loadAllOfflineProgress: return 0 - case let .m_deleteProgress__for_blockID(p0): return p0.intValue - case .m_deleteAllProgress: return 0 - case let .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(p0, p1): return p0.intValue + p1.intValue - case let .m_updateTask__task_task(p0): return p0.intValue - case let .m_downloadDataTask__for_blockId(p0): return p0.intValue - case .m_getDownloadDataTasks: return 0 - case let .m_getDownloadDataTasksForCourse__courseId(p0): return p0.intValue - case let .m_deleteDownloadDataTasks__ids_ids(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_set__userId_userId: return ".set(userId:)" - case .m_getUserID: return ".getUserID()" - case .m_publisher: return ".publisher()" - case .m_addToDownloadQueue__tasks_tasks: return ".addToDownloadQueue(tasks:)" - case .m_saveOfflineProgress__progress_progress: return ".saveOfflineProgress(progress:)" - case .m_loadProgress__for_blockID: return ".loadProgress(for:)" - case .m_loadAllOfflineProgress: return ".loadAllOfflineProgress()" - case .m_deleteProgress__for_blockID: return ".deleteProgress(for:)" - case .m_deleteAllProgress: return ".deleteAllProgress()" - case .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality: return ".addToDownloadQueue(blocks:downloadQuality:)" - case .m_updateTask__task_task: return ".updateTask(task:)" - case .m_downloadDataTask__for_blockId: return ".downloadDataTask(for:)" - case .m_getDownloadDataTasks: return ".getDownloadDataTasks()" - case .m_getDownloadDataTasksForCourse__courseId: return ".getDownloadDataTasksForCourse(_:)" - case .m_deleteDownloadDataTasks__ids_ids: return ".deleteDownloadDataTasks(ids:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getUserID(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @MainActor - public static func publisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_publisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadProgress(for blockID: Parameter, willReturn: OfflineProgress?...) -> MethodStub { - return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadAllOfflineProgress(willReturn: [OfflineProgress]...) -> MethodStub { - return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadDataTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getUserID(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func loadProgress(for blockID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [OfflineProgress?] = [] - let given: Given = { return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (OfflineProgress?).self) - willProduce(stubber) - return given - } - public static func loadAllOfflineProgress(willProduce: (Stubber<[OfflineProgress]>) -> Void) -> MethodStub { - let willReturn: [[OfflineProgress]] = [] - let given: Given = { return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([OfflineProgress]).self) - willProduce(stubber) - return given - } - public static func downloadDataTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - @MainActor - public static func publisher(willThrow: Error...) -> MethodStub { - return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) - } - @MainActor - public static func publisher(willProduce: (StubberThrows>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func set(userId: Parameter) -> Verify { return Verify(method: .m_set__userId_userId(`userId`))} - public static func getUserID() -> Verify { return Verify(method: .m_getUserID)} - @MainActor - public static func publisher() -> Verify { return Verify(method: .m_publisher)} - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>) -> Verify { return Verify(method: .m_addToDownloadQueue__tasks_tasks(`tasks`))} - public static func saveOfflineProgress(progress: Parameter) -> Verify { return Verify(method: .m_saveOfflineProgress__progress_progress(`progress`))} - public static func loadProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_loadProgress__for_blockID(`blockID`))} - public static func loadAllOfflineProgress() -> Verify { return Verify(method: .m_loadAllOfflineProgress)} - public static func deleteProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_deleteProgress__for_blockID(`blockID`))} - public static func deleteAllProgress() -> Verify { return Verify(method: .m_deleteAllProgress)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`))} - public static func updateTask(task: Parameter) -> Verify { return Verify(method: .m_updateTask__task_task(`task`))} - public static func downloadDataTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadDataTask__for_blockId(`blockId`))} - public static func getDownloadDataTasks() -> Verify { return Verify(method: .m_getDownloadDataTasks)} - public static func getDownloadDataTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`))} - public static func deleteDownloadDataTasks(ids: Parameter<[String]>) -> Verify { return Verify(method: .m_deleteDownloadDataTasks__ids_ids(`ids`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func set(userId: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_set__userId_userId(`userId`), performs: perform) - } - public static func getUserID(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getUserID, performs: perform) - } - @MainActor - public static func publisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_publisher, performs: perform) - } - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>, perform: @escaping ([DownloadDataTask]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__tasks_tasks(`tasks`), performs: perform) - } - public static func saveOfflineProgress(progress: Parameter, perform: @escaping (OfflineProgress) -> Void) -> Perform { - return Perform(method: .m_saveOfflineProgress__progress_progress(`progress`), performs: perform) - } - public static func loadProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_loadProgress__for_blockID(`blockID`), performs: perform) - } - public static func loadAllOfflineProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_loadAllOfflineProgress, performs: perform) - } - public static func deleteProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_deleteProgress__for_blockID(`blockID`), performs: perform) - } - public static func deleteAllProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAllProgress, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter, perform: @escaping ([CourseBlock], DownloadQuality) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`), performs: perform) - } - public static func updateTask(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_updateTask__task_task(`task`), performs: perform) - } - public static func downloadDataTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadDataTask__for_blockId(`blockId`), performs: perform) - } - public static func getDownloadDataTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasks, performs: perform) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func deleteDownloadDataTasks(ids: Parameter<[String]>, perform: @escaping ([String]) -> Void) -> Perform { - return Perform(method: .m_deleteDownloadDataTasks__ids_ids(`ids`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreStorage - -open class CoreStorageMock: CoreStorage, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var accessToken: String? { - get { invocations.append(.p_accessToken_get); return __p_accessToken ?? optionalGivenGetterValue(.p_accessToken_get, "CoreStorageMock - stub value for accessToken was not defined") } - set { invocations.append(.p_accessToken_set(.value(newValue))); __p_accessToken = newValue } - } - private var __p_accessToken: (String)? - - public var refreshToken: String? { - get { invocations.append(.p_refreshToken_get); return __p_refreshToken ?? optionalGivenGetterValue(.p_refreshToken_get, "CoreStorageMock - stub value for refreshToken was not defined") } - set { invocations.append(.p_refreshToken_set(.value(newValue))); __p_refreshToken = newValue } - } - private var __p_refreshToken: (String)? - - public var pushToken: String? { - get { invocations.append(.p_pushToken_get); return __p_pushToken ?? optionalGivenGetterValue(.p_pushToken_get, "CoreStorageMock - stub value for pushToken was not defined") } - set { invocations.append(.p_pushToken_set(.value(newValue))); __p_pushToken = newValue } - } - private var __p_pushToken: (String)? - - public var appleSignFullName: String? { - get { invocations.append(.p_appleSignFullName_get); return __p_appleSignFullName ?? optionalGivenGetterValue(.p_appleSignFullName_get, "CoreStorageMock - stub value for appleSignFullName was not defined") } - set { invocations.append(.p_appleSignFullName_set(.value(newValue))); __p_appleSignFullName = newValue } - } - private var __p_appleSignFullName: (String)? - - public var appleSignEmail: String? { - get { invocations.append(.p_appleSignEmail_get); return __p_appleSignEmail ?? optionalGivenGetterValue(.p_appleSignEmail_get, "CoreStorageMock - stub value for appleSignEmail was not defined") } - set { invocations.append(.p_appleSignEmail_set(.value(newValue))); __p_appleSignEmail = newValue } - } - private var __p_appleSignEmail: (String)? - - public var cookiesDate: Date? { - get { invocations.append(.p_cookiesDate_get); return __p_cookiesDate ?? optionalGivenGetterValue(.p_cookiesDate_get, "CoreStorageMock - stub value for cookiesDate was not defined") } - set { invocations.append(.p_cookiesDate_set(.value(newValue))); __p_cookiesDate = newValue } - } - private var __p_cookiesDate: (Date)? - - public var reviewLastShownVersion: String? { - get { invocations.append(.p_reviewLastShownVersion_get); return __p_reviewLastShownVersion ?? optionalGivenGetterValue(.p_reviewLastShownVersion_get, "CoreStorageMock - stub value for reviewLastShownVersion was not defined") } - set { invocations.append(.p_reviewLastShownVersion_set(.value(newValue))); __p_reviewLastShownVersion = newValue } - } - private var __p_reviewLastShownVersion: (String)? - - public var lastReviewDate: Date? { - get { invocations.append(.p_lastReviewDate_get); return __p_lastReviewDate ?? optionalGivenGetterValue(.p_lastReviewDate_get, "CoreStorageMock - stub value for lastReviewDate was not defined") } - set { invocations.append(.p_lastReviewDate_set(.value(newValue))); __p_lastReviewDate = newValue } - } - private var __p_lastReviewDate: (Date)? - - public var user: DataLayer.User? { - get { invocations.append(.p_user_get); return __p_user ?? optionalGivenGetterValue(.p_user_get, "CoreStorageMock - stub value for user was not defined") } - set { invocations.append(.p_user_set(.value(newValue))); __p_user = newValue } - } - private var __p_user: (DataLayer.User)? - - public var userSettings: UserSettings? { - get { invocations.append(.p_userSettings_get); return __p_userSettings ?? optionalGivenGetterValue(.p_userSettings_get, "CoreStorageMock - stub value for userSettings was not defined") } - set { invocations.append(.p_userSettings_set(.value(newValue))); __p_userSettings = newValue } - } - private var __p_userSettings: (UserSettings)? - - public var resetAppSupportDirectoryUserData: Bool? { - get { invocations.append(.p_resetAppSupportDirectoryUserData_get); return __p_resetAppSupportDirectoryUserData ?? optionalGivenGetterValue(.p_resetAppSupportDirectoryUserData_get, "CoreStorageMock - stub value for resetAppSupportDirectoryUserData was not defined") } - set { invocations.append(.p_resetAppSupportDirectoryUserData_set(.value(newValue))); __p_resetAppSupportDirectoryUserData = newValue } - } - private var __p_resetAppSupportDirectoryUserData: (Bool)? - - public var useRelativeDates: Bool { - get { invocations.append(.p_useRelativeDates_get); return __p_useRelativeDates ?? givenGetterValue(.p_useRelativeDates_get, "CoreStorageMock - stub value for useRelativeDates was not defined") } - set { invocations.append(.p_useRelativeDates_set(.value(newValue))); __p_useRelativeDates = newValue } - } - private var __p_useRelativeDates: (Bool)? - - public var lastUsedSocialAuth: String? { - get { invocations.append(.p_lastUsedSocialAuth_get); return __p_lastUsedSocialAuth ?? optionalGivenGetterValue(.p_lastUsedSocialAuth_get, "CoreStorageMock - stub value for lastUsedSocialAuth was not defined") } - set { invocations.append(.p_lastUsedSocialAuth_set(.value(newValue))); __p_lastUsedSocialAuth = newValue } - } - private var __p_lastUsedSocialAuth: (String)? - - public var latestAvailableAppVersion: String? { - get { invocations.append(.p_latestAvailableAppVersion_get); return __p_latestAvailableAppVersion ?? optionalGivenGetterValue(.p_latestAvailableAppVersion_get, "CoreStorageMock - stub value for latestAvailableAppVersion was not defined") } - set { invocations.append(.p_latestAvailableAppVersion_set(.value(newValue))); __p_latestAvailableAppVersion = newValue } - } - private var __p_latestAvailableAppVersion: (String)? - - public var updateAppRequired: Bool { - get { invocations.append(.p_updateAppRequired_get); return __p_updateAppRequired ?? givenGetterValue(.p_updateAppRequired_get, "CoreStorageMock - stub value for updateAppRequired was not defined") } - set { invocations.append(.p_updateAppRequired_set(.value(newValue))); __p_updateAppRequired = newValue } - } - private var __p_updateAppRequired: (Bool)? - - - - - - open func clear() { - addInvocation(.m_clear) - let perform = methodPerformValue(.m_clear) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_clear - case p_accessToken_get - case p_accessToken_set(Parameter) - case p_refreshToken_get - case p_refreshToken_set(Parameter) - case p_pushToken_get - case p_pushToken_set(Parameter) - case p_appleSignFullName_get - case p_appleSignFullName_set(Parameter) - case p_appleSignEmail_get - case p_appleSignEmail_set(Parameter) - case p_cookiesDate_get - case p_cookiesDate_set(Parameter) - case p_reviewLastShownVersion_get - case p_reviewLastShownVersion_set(Parameter) - case p_lastReviewDate_get - case p_lastReviewDate_set(Parameter) - case p_user_get - case p_user_set(Parameter) - case p_userSettings_get - case p_userSettings_set(Parameter) - case p_resetAppSupportDirectoryUserData_get - case p_resetAppSupportDirectoryUserData_set(Parameter) - case p_useRelativeDates_get - case p_useRelativeDates_set(Parameter) - case p_lastUsedSocialAuth_get - case p_lastUsedSocialAuth_set(Parameter) - case p_latestAvailableAppVersion_get - case p_latestAvailableAppVersion_set(Parameter) - case p_updateAppRequired_get - case p_updateAppRequired_set(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_clear, .m_clear): return .match - case (.p_accessToken_get,.p_accessToken_get): return Matcher.ComparisonResult.match - case (.p_accessToken_set(let left),.p_accessToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_refreshToken_get,.p_refreshToken_get): return Matcher.ComparisonResult.match - case (.p_refreshToken_set(let left),.p_refreshToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_pushToken_get,.p_pushToken_get): return Matcher.ComparisonResult.match - case (.p_pushToken_set(let left),.p_pushToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignFullName_get,.p_appleSignFullName_get): return Matcher.ComparisonResult.match - case (.p_appleSignFullName_set(let left),.p_appleSignFullName_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignEmail_get,.p_appleSignEmail_get): return Matcher.ComparisonResult.match - case (.p_appleSignEmail_set(let left),.p_appleSignEmail_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_cookiesDate_get,.p_cookiesDate_get): return Matcher.ComparisonResult.match - case (.p_cookiesDate_set(let left),.p_cookiesDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_reviewLastShownVersion_get,.p_reviewLastShownVersion_get): return Matcher.ComparisonResult.match - case (.p_reviewLastShownVersion_set(let left),.p_reviewLastShownVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastReviewDate_get,.p_lastReviewDate_get): return Matcher.ComparisonResult.match - case (.p_lastReviewDate_set(let left),.p_lastReviewDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_user_get,.p_user_get): return Matcher.ComparisonResult.match - case (.p_user_set(let left),.p_user_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_userSettings_get,.p_userSettings_get): return Matcher.ComparisonResult.match - case (.p_userSettings_set(let left),.p_userSettings_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_resetAppSupportDirectoryUserData_get,.p_resetAppSupportDirectoryUserData_get): return Matcher.ComparisonResult.match - case (.p_resetAppSupportDirectoryUserData_set(let left),.p_resetAppSupportDirectoryUserData_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_useRelativeDates_get,.p_useRelativeDates_get): return Matcher.ComparisonResult.match - case (.p_useRelativeDates_set(let left),.p_useRelativeDates_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastUsedSocialAuth_get,.p_lastUsedSocialAuth_get): return Matcher.ComparisonResult.match - case (.p_lastUsedSocialAuth_set(let left),.p_lastUsedSocialAuth_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_latestAvailableAppVersion_get,.p_latestAvailableAppVersion_get): return Matcher.ComparisonResult.match - case (.p_latestAvailableAppVersion_set(let left),.p_latestAvailableAppVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_updateAppRequired_get,.p_updateAppRequired_get): return Matcher.ComparisonResult.match - case (.p_updateAppRequired_set(let left),.p_updateAppRequired_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_clear: return 0 - case .p_accessToken_get: return 0 - case .p_accessToken_set(let newValue): return newValue.intValue - case .p_refreshToken_get: return 0 - case .p_refreshToken_set(let newValue): return newValue.intValue - case .p_pushToken_get: return 0 - case .p_pushToken_set(let newValue): return newValue.intValue - case .p_appleSignFullName_get: return 0 - case .p_appleSignFullName_set(let newValue): return newValue.intValue - case .p_appleSignEmail_get: return 0 - case .p_appleSignEmail_set(let newValue): return newValue.intValue - case .p_cookiesDate_get: return 0 - case .p_cookiesDate_set(let newValue): return newValue.intValue - case .p_reviewLastShownVersion_get: return 0 - case .p_reviewLastShownVersion_set(let newValue): return newValue.intValue - case .p_lastReviewDate_get: return 0 - case .p_lastReviewDate_set(let newValue): return newValue.intValue - case .p_user_get: return 0 - case .p_user_set(let newValue): return newValue.intValue - case .p_userSettings_get: return 0 - case .p_userSettings_set(let newValue): return newValue.intValue - case .p_resetAppSupportDirectoryUserData_get: return 0 - case .p_resetAppSupportDirectoryUserData_set(let newValue): return newValue.intValue - case .p_useRelativeDates_get: return 0 - case .p_useRelativeDates_set(let newValue): return newValue.intValue - case .p_lastUsedSocialAuth_get: return 0 - case .p_lastUsedSocialAuth_set(let newValue): return newValue.intValue - case .p_latestAvailableAppVersion_get: return 0 - case .p_latestAvailableAppVersion_set(let newValue): return newValue.intValue - case .p_updateAppRequired_get: return 0 - case .p_updateAppRequired_set(let newValue): return newValue.intValue - } - } - func assertionName() -> String { - switch self { - case .m_clear: return ".clear()" - case .p_accessToken_get: return "[get] .accessToken" - case .p_accessToken_set: return "[set] .accessToken" - case .p_refreshToken_get: return "[get] .refreshToken" - case .p_refreshToken_set: return "[set] .refreshToken" - case .p_pushToken_get: return "[get] .pushToken" - case .p_pushToken_set: return "[set] .pushToken" - case .p_appleSignFullName_get: return "[get] .appleSignFullName" - case .p_appleSignFullName_set: return "[set] .appleSignFullName" - case .p_appleSignEmail_get: return "[get] .appleSignEmail" - case .p_appleSignEmail_set: return "[set] .appleSignEmail" - case .p_cookiesDate_get: return "[get] .cookiesDate" - case .p_cookiesDate_set: return "[set] .cookiesDate" - case .p_reviewLastShownVersion_get: return "[get] .reviewLastShownVersion" - case .p_reviewLastShownVersion_set: return "[set] .reviewLastShownVersion" - case .p_lastReviewDate_get: return "[get] .lastReviewDate" - case .p_lastReviewDate_set: return "[set] .lastReviewDate" - case .p_user_get: return "[get] .user" - case .p_user_set: return "[set] .user" - case .p_userSettings_get: return "[get] .userSettings" - case .p_userSettings_set: return "[set] .userSettings" - case .p_resetAppSupportDirectoryUserData_get: return "[get] .resetAppSupportDirectoryUserData" - case .p_resetAppSupportDirectoryUserData_set: return "[set] .resetAppSupportDirectoryUserData" - case .p_useRelativeDates_get: return "[get] .useRelativeDates" - case .p_useRelativeDates_set: return "[set] .useRelativeDates" - case .p_lastUsedSocialAuth_get: return "[get] .lastUsedSocialAuth" - case .p_lastUsedSocialAuth_set: return "[set] .lastUsedSocialAuth" - case .p_latestAvailableAppVersion_get: return "[get] .latestAvailableAppVersion" - case .p_latestAvailableAppVersion_set: return "[set] .latestAvailableAppVersion" - case .p_updateAppRequired_get: return "[get] .updateAppRequired" - case .p_updateAppRequired_set: return "[set] .updateAppRequired" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func accessToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_accessToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func refreshToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_refreshToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func pushToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_pushToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignFullName(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignFullName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignEmail(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func cookiesDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_cookiesDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func reviewLastShownVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_reviewLastShownVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastReviewDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_lastReviewDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func user(getter defaultValue: DataLayer.User?...) -> PropertyStub { - return Given(method: .p_user_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func userSettings(getter defaultValue: UserSettings?...) -> PropertyStub { - return Given(method: .p_userSettings_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func resetAppSupportDirectoryUserData(getter defaultValue: Bool?...) -> PropertyStub { - return Given(method: .p_resetAppSupportDirectoryUserData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func useRelativeDates(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_useRelativeDates_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastUsedSocialAuth(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_lastUsedSocialAuth_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func latestAvailableAppVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_latestAvailableAppVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func updateAppRequired(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_updateAppRequired_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func clear() -> Verify { return Verify(method: .m_clear)} - public static var accessToken: Verify { return Verify(method: .p_accessToken_get) } - public static func accessToken(set newValue: Parameter) -> Verify { return Verify(method: .p_accessToken_set(newValue)) } - public static var refreshToken: Verify { return Verify(method: .p_refreshToken_get) } - public static func refreshToken(set newValue: Parameter) -> Verify { return Verify(method: .p_refreshToken_set(newValue)) } - public static var pushToken: Verify { return Verify(method: .p_pushToken_get) } - public static func pushToken(set newValue: Parameter) -> Verify { return Verify(method: .p_pushToken_set(newValue)) } - public static var appleSignFullName: Verify { return Verify(method: .p_appleSignFullName_get) } - public static func appleSignFullName(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignFullName_set(newValue)) } - public static var appleSignEmail: Verify { return Verify(method: .p_appleSignEmail_get) } - public static func appleSignEmail(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignEmail_set(newValue)) } - public static var cookiesDate: Verify { return Verify(method: .p_cookiesDate_get) } - public static func cookiesDate(set newValue: Parameter) -> Verify { return Verify(method: .p_cookiesDate_set(newValue)) } - public static var reviewLastShownVersion: Verify { return Verify(method: .p_reviewLastShownVersion_get) } - public static func reviewLastShownVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_reviewLastShownVersion_set(newValue)) } - public static var lastReviewDate: Verify { return Verify(method: .p_lastReviewDate_get) } - public static func lastReviewDate(set newValue: Parameter) -> Verify { return Verify(method: .p_lastReviewDate_set(newValue)) } - public static var user: Verify { return Verify(method: .p_user_get) } - public static func user(set newValue: Parameter) -> Verify { return Verify(method: .p_user_set(newValue)) } - public static var userSettings: Verify { return Verify(method: .p_userSettings_get) } - public static func userSettings(set newValue: Parameter) -> Verify { return Verify(method: .p_userSettings_set(newValue)) } - public static var resetAppSupportDirectoryUserData: Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_get) } - public static func resetAppSupportDirectoryUserData(set newValue: Parameter) -> Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_set(newValue)) } - public static var useRelativeDates: Verify { return Verify(method: .p_useRelativeDates_get) } - public static func useRelativeDates(set newValue: Parameter) -> Verify { return Verify(method: .p_useRelativeDates_set(newValue)) } - public static var lastUsedSocialAuth: Verify { return Verify(method: .p_lastUsedSocialAuth_get) } - public static func lastUsedSocialAuth(set newValue: Parameter) -> Verify { return Verify(method: .p_lastUsedSocialAuth_set(newValue)) } - public static var latestAvailableAppVersion: Verify { return Verify(method: .p_latestAvailableAppVersion_get) } - public static func latestAvailableAppVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_latestAvailableAppVersion_set(newValue)) } - public static var updateAppRequired: Verify { return Verify(method: .p_updateAppRequired_get) } - public static func updateAppRequired(set newValue: Parameter) -> Verify { return Verify(method: .p_updateAppRequired_set(newValue)) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func clear(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_clear, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CourseStructureManagerProtocol - -open class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getLoadedCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func shiftDueDates(courseID: String) throws { - addInvocation(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - do { - _ = try methodReturnValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - - fileprivate enum MethodType { - case m_getCourseBlocks__courseID_courseID(Parameter) - case m_getLoadedCourseBlocks__courseID_courseID(Parameter) - case m_shiftDueDates__courseID_courseID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseBlocks__courseID_courseID(let lhsCourseid), .m_getCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getLoadedCourseBlocks__courseID_courseID(let lhsCourseid), .m_getLoadedCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_shiftDueDates__courseID_courseID(let lhsCourseid), .m_shiftDueDates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_getLoadedCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_shiftDueDates__courseID_courseID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getCourseBlocks__courseID_courseID: return ".getCourseBlocks(courseID:)" - case .m_getLoadedCourseBlocks__courseID_courseID: return ".getLoadedCourseBlocks(courseID:)" - case .m_shiftDueDates__courseID_courseID: return ".shiftDueDates(courseID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getLoadedCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func shiftDueDates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func shiftDueDates(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseBlocks__courseID_courseID(`courseID`))} - public static func getLoadedCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`))} - public static func shiftDueDates(courseID: Parameter) -> Verify { return Verify(method: .m_shiftDueDates__courseID_courseID(`courseID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func getLoadedCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func shiftDueDates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_shiftDueDates__courseID_courseID(`courseID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DiscoveryAnalytics - -open class DiscoveryAnalyticsMock: DiscoveryAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func discoverySearchBarClicked() { - addInvocation(.m_discoverySearchBarClicked) - let perform = methodPerformValue(.m_discoverySearchBarClicked) as? () -> Void - perform?() - } - - open func discoveryCoursesSearch(label: String, coursesCount: Int) { - addInvocation(.m_discoveryCoursesSearch__label_labelcoursesCount_coursesCount(Parameter.value(`label`), Parameter.value(`coursesCount`))) - let perform = methodPerformValue(.m_discoveryCoursesSearch__label_labelcoursesCount_coursesCount(Parameter.value(`label`), Parameter.value(`coursesCount`))) as? (String, Int) -> Void - perform?(`label`, `coursesCount`) - } - - open func discoveryCourseClicked(courseID: String, courseName: String) { - addInvocation(.m_discoveryCourseClicked__courseID_courseIDcourseName_courseName(Parameter.value(`courseID`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_discoveryCourseClicked__courseID_courseIDcourseName_courseName(Parameter.value(`courseID`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseID`, `courseName`) - } - - open func viewCourseClicked(courseId: String, courseName: String) { - addInvocation(.m_viewCourseClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_viewCourseClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseEnrollClicked(courseId: String, courseName: String) { - addInvocation(.m_courseEnrollClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseEnrollClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func courseEnrollSuccess(courseId: String, courseName: String) { - addInvocation(.m_courseEnrollSuccess__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_courseEnrollSuccess__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func externalLinkOpen(url: String, screen: String) { - addInvocation(.m_externalLinkOpen__url_urlscreen_screen(Parameter.value(`url`), Parameter.value(`screen`))) - let perform = methodPerformValue(.m_externalLinkOpen__url_urlscreen_screen(Parameter.value(`url`), Parameter.value(`screen`))) as? (String, String) -> Void - perform?(`url`, `screen`) - } - - open func externalLinkOpenAction(url: String, screen: String, action: String) { - addInvocation(.m_externalLinkOpenAction__url_urlscreen_screenaction_action(Parameter.value(`url`), Parameter.value(`screen`), Parameter.value(`action`))) - let perform = methodPerformValue(.m_externalLinkOpenAction__url_urlscreen_screenaction_action(Parameter.value(`url`), Parameter.value(`screen`), Parameter.value(`action`))) as? (String, String, String) -> Void - perform?(`url`, `screen`, `action`) - } - - open func discoveryScreenEvent(event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_discoveryScreenEvent__event_eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_discoveryScreenEvent__event_eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - - fileprivate enum MethodType { - case m_discoverySearchBarClicked - case m_discoveryCoursesSearch__label_labelcoursesCount_coursesCount(Parameter, Parameter) - case m_discoveryCourseClicked__courseID_courseIDcourseName_courseName(Parameter, Parameter) - case m_viewCourseClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseEnrollClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_courseEnrollSuccess__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_externalLinkOpen__url_urlscreen_screen(Parameter, Parameter) - case m_externalLinkOpenAction__url_urlscreen_screenaction_action(Parameter, Parameter, Parameter) - case m_discoveryScreenEvent__event_eventbiValue_biValue(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_discoverySearchBarClicked, .m_discoverySearchBarClicked): return .match - - case (.m_discoveryCoursesSearch__label_labelcoursesCount_coursesCount(let lhsLabel, let lhsCoursescount), .m_discoveryCoursesSearch__label_labelcoursesCount_coursesCount(let rhsLabel, let rhsCoursescount)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsLabel, rhs: rhsLabel, with: matcher), lhsLabel, rhsLabel, "label")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursescount, rhs: rhsCoursescount, with: matcher), lhsCoursescount, rhsCoursescount, "coursesCount")) - return Matcher.ComparisonResult(results) - - case (.m_discoveryCourseClicked__courseID_courseIDcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_discoveryCourseClicked__courseID_courseIDcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_viewCourseClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_viewCourseClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseEnrollClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseEnrollClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_courseEnrollSuccess__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_courseEnrollSuccess__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_externalLinkOpen__url_urlscreen_screen(let lhsUrl, let lhsScreen), .m_externalLinkOpen__url_urlscreen_screen(let rhsUrl, let rhsScreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsScreen, rhs: rhsScreen, with: matcher), lhsScreen, rhsScreen, "screen")) - return Matcher.ComparisonResult(results) - - case (.m_externalLinkOpenAction__url_urlscreen_screenaction_action(let lhsUrl, let lhsScreen, let lhsAction), .m_externalLinkOpenAction__url_urlscreen_screenaction_action(let rhsUrl, let rhsScreen, let rhsAction)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsScreen, rhs: rhsScreen, with: matcher), lhsScreen, rhsScreen, "screen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - return Matcher.ComparisonResult(results) - - case (.m_discoveryScreenEvent__event_eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_discoveryScreenEvent__event_eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_discoverySearchBarClicked: return 0 - case let .m_discoveryCoursesSearch__label_labelcoursesCount_coursesCount(p0, p1): return p0.intValue + p1.intValue - case let .m_discoveryCourseClicked__courseID_courseIDcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_viewCourseClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseEnrollClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_courseEnrollSuccess__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_externalLinkOpen__url_urlscreen_screen(p0, p1): return p0.intValue + p1.intValue - case let .m_externalLinkOpenAction__url_urlscreen_screenaction_action(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_discoveryScreenEvent__event_eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_discoverySearchBarClicked: return ".discoverySearchBarClicked()" - case .m_discoveryCoursesSearch__label_labelcoursesCount_coursesCount: return ".discoveryCoursesSearch(label:coursesCount:)" - case .m_discoveryCourseClicked__courseID_courseIDcourseName_courseName: return ".discoveryCourseClicked(courseID:courseName:)" - case .m_viewCourseClicked__courseId_courseIdcourseName_courseName: return ".viewCourseClicked(courseId:courseName:)" - case .m_courseEnrollClicked__courseId_courseIdcourseName_courseName: return ".courseEnrollClicked(courseId:courseName:)" - case .m_courseEnrollSuccess__courseId_courseIdcourseName_courseName: return ".courseEnrollSuccess(courseId:courseName:)" - case .m_externalLinkOpen__url_urlscreen_screen: return ".externalLinkOpen(url:screen:)" - case .m_externalLinkOpenAction__url_urlscreen_screenaction_action: return ".externalLinkOpenAction(url:screen:action:)" - case .m_discoveryScreenEvent__event_eventbiValue_biValue: return ".discoveryScreenEvent(event:biValue:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func discoverySearchBarClicked() -> Verify { return Verify(method: .m_discoverySearchBarClicked)} - public static func discoveryCoursesSearch(label: Parameter, coursesCount: Parameter) -> Verify { return Verify(method: .m_discoveryCoursesSearch__label_labelcoursesCount_coursesCount(`label`, `coursesCount`))} - public static func discoveryCourseClicked(courseID: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_discoveryCourseClicked__courseID_courseIDcourseName_courseName(`courseID`, `courseName`))} - public static func viewCourseClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_viewCourseClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseEnrollClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseEnrollClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func courseEnrollSuccess(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_courseEnrollSuccess__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func externalLinkOpen(url: Parameter, screen: Parameter) -> Verify { return Verify(method: .m_externalLinkOpen__url_urlscreen_screen(`url`, `screen`))} - public static func externalLinkOpenAction(url: Parameter, screen: Parameter, action: Parameter) -> Verify { return Verify(method: .m_externalLinkOpenAction__url_urlscreen_screenaction_action(`url`, `screen`, `action`))} - public static func discoveryScreenEvent(event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_discoveryScreenEvent__event_eventbiValue_biValue(`event`, `biValue`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func discoverySearchBarClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_discoverySearchBarClicked, performs: perform) - } - public static func discoveryCoursesSearch(label: Parameter, coursesCount: Parameter, perform: @escaping (String, Int) -> Void) -> Perform { - return Perform(method: .m_discoveryCoursesSearch__label_labelcoursesCount_coursesCount(`label`, `coursesCount`), performs: perform) - } - public static func discoveryCourseClicked(courseID: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_discoveryCourseClicked__courseID_courseIDcourseName_courseName(`courseID`, `courseName`), performs: perform) - } - public static func viewCourseClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_viewCourseClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseEnrollClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseEnrollClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func courseEnrollSuccess(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_courseEnrollSuccess__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func externalLinkOpen(url: Parameter, screen: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_externalLinkOpen__url_urlscreen_screen(`url`, `screen`), performs: perform) - } - public static func externalLinkOpenAction(url: Parameter, screen: Parameter, action: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_externalLinkOpenAction__url_urlscreen_screenaction_action(`url`, `screen`, `action`), performs: perform) - } - public static func discoveryScreenEvent(event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_discoveryScreenEvent__event_eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DiscoveryInteractorProtocol - -open class DiscoveryInteractorProtocolMock: DiscoveryInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func discovery(page: Int) throws -> [CourseItem] { - addInvocation(.m_discovery__page_page(Parameter.value(`page`))) - let perform = methodPerformValue(.m_discovery__page_page(Parameter.value(`page`))) as? (Int) -> Void - perform?(`page`) - var __value: [CourseItem] - do { - __value = try methodReturnValue(.m_discovery__page_page(Parameter.value(`page`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for discovery(page: Int). Use given") - Failure("Stub return value not specified for discovery(page: Int). Use given") - } catch { - throw error - } - return __value - } - - open func discoveryOffline() throws -> [CourseItem] { - addInvocation(.m_discoveryOffline) - let perform = methodPerformValue(.m_discoveryOffline) as? () -> Void - perform?() - var __value: [CourseItem] - do { - __value = try methodReturnValue(.m_discoveryOffline).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for discoveryOffline(). Use given") - Failure("Stub return value not specified for discoveryOffline(). Use given") - } catch { - throw error - } - return __value - } - - open func search(page: Int, searchTerm: String) throws -> [CourseItem] { - addInvocation(.m_search__page_pagesearchTerm_searchTerm(Parameter.value(`page`), Parameter.value(`searchTerm`))) - let perform = methodPerformValue(.m_search__page_pagesearchTerm_searchTerm(Parameter.value(`page`), Parameter.value(`searchTerm`))) as? (Int, String) -> Void - perform?(`page`, `searchTerm`) - var __value: [CourseItem] - do { - __value = try methodReturnValue(.m_search__page_pagesearchTerm_searchTerm(Parameter.value(`page`), Parameter.value(`searchTerm`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for search(page: Int, searchTerm: String). Use given") - Failure("Stub return value not specified for search(page: Int, searchTerm: String). Use given") - } catch { - throw error - } - return __value - } - - open func getLoadedCourseDetails(courseID: String) throws -> CourseDetails { - addInvocation(.m_getLoadedCourseDetails__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getLoadedCourseDetails__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseDetails - do { - __value = try methodReturnValue(.m_getLoadedCourseDetails__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getLoadedCourseDetails(courseID: String). Use given") - Failure("Stub return value not specified for getLoadedCourseDetails(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCourseDetails(courseID: String) throws -> CourseDetails { - addInvocation(.m_getCourseDetails__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseDetails__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseDetails - do { - __value = try methodReturnValue(.m_getCourseDetails__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseDetails(courseID: String). Use given") - Failure("Stub return value not specified for getCourseDetails(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func enrollToCourse(courseID: String) throws -> Bool { - addInvocation(.m_enrollToCourse__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_enrollToCourse__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: Bool - do { - __value = try methodReturnValue(.m_enrollToCourse__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for enrollToCourse(courseID: String). Use given") - Failure("Stub return value not specified for enrollToCourse(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_discovery__page_page(Parameter) - case m_discoveryOffline - case m_search__page_pagesearchTerm_searchTerm(Parameter, Parameter) - case m_getLoadedCourseDetails__courseID_courseID(Parameter) - case m_getCourseDetails__courseID_courseID(Parameter) - case m_enrollToCourse__courseID_courseID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_discovery__page_page(let lhsPage), .m_discovery__page_page(let rhsPage)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPage, rhs: rhsPage, with: matcher), lhsPage, rhsPage, "page")) - return Matcher.ComparisonResult(results) - - case (.m_discoveryOffline, .m_discoveryOffline): return .match - - case (.m_search__page_pagesearchTerm_searchTerm(let lhsPage, let lhsSearchterm), .m_search__page_pagesearchTerm_searchTerm(let rhsPage, let rhsSearchterm)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPage, rhs: rhsPage, with: matcher), lhsPage, rhsPage, "page")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchterm, rhs: rhsSearchterm, with: matcher), lhsSearchterm, rhsSearchterm, "searchTerm")) - return Matcher.ComparisonResult(results) - - case (.m_getLoadedCourseDetails__courseID_courseID(let lhsCourseid), .m_getLoadedCourseDetails__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getCourseDetails__courseID_courseID(let lhsCourseid), .m_getCourseDetails__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_enrollToCourse__courseID_courseID(let lhsCourseid), .m_enrollToCourse__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_discovery__page_page(p0): return p0.intValue - case .m_discoveryOffline: return 0 - case let .m_search__page_pagesearchTerm_searchTerm(p0, p1): return p0.intValue + p1.intValue - case let .m_getLoadedCourseDetails__courseID_courseID(p0): return p0.intValue - case let .m_getCourseDetails__courseID_courseID(p0): return p0.intValue - case let .m_enrollToCourse__courseID_courseID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_discovery__page_page: return ".discovery(page:)" - case .m_discoveryOffline: return ".discoveryOffline()" - case .m_search__page_pagesearchTerm_searchTerm: return ".search(page:searchTerm:)" - case .m_getLoadedCourseDetails__courseID_courseID: return ".getLoadedCourseDetails(courseID:)" - case .m_getCourseDetails__courseID_courseID: return ".getCourseDetails(courseID:)" - case .m_enrollToCourse__courseID_courseID: return ".enrollToCourse(courseID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func discovery(page: Parameter, willReturn: [CourseItem]...) -> MethodStub { - return Given(method: .m_discovery__page_page(`page`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func discoveryOffline(willReturn: [CourseItem]...) -> MethodStub { - return Given(method: .m_discoveryOffline, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func search(page: Parameter, searchTerm: Parameter, willReturn: [CourseItem]...) -> MethodStub { - return Given(method: .m_search__page_pagesearchTerm_searchTerm(`page`, `searchTerm`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getLoadedCourseDetails(courseID: Parameter, willReturn: CourseDetails...) -> MethodStub { - return Given(method: .m_getLoadedCourseDetails__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseDetails(courseID: Parameter, willReturn: CourseDetails...) -> MethodStub { - return Given(method: .m_getCourseDetails__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func enrollToCourse(courseID: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_enrollToCourse__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func discovery(page: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_discovery__page_page(`page`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func discovery(page: Parameter, willProduce: (StubberThrows<[CourseItem]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_discovery__page_page(`page`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([CourseItem]).self) - willProduce(stubber) - return given - } - public static func discoveryOffline(willThrow: Error...) -> MethodStub { - return Given(method: .m_discoveryOffline, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func discoveryOffline(willProduce: (StubberThrows<[CourseItem]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_discoveryOffline, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([CourseItem]).self) - willProduce(stubber) - return given - } - public static func search(page: Parameter, searchTerm: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_search__page_pagesearchTerm_searchTerm(`page`, `searchTerm`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func search(page: Parameter, searchTerm: Parameter, willProduce: (StubberThrows<[CourseItem]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_search__page_pagesearchTerm_searchTerm(`page`, `searchTerm`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([CourseItem]).self) - willProduce(stubber) - return given - } - public static func getLoadedCourseDetails(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getLoadedCourseDetails__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getLoadedCourseDetails(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getLoadedCourseDetails__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseDetails).self) - willProduce(stubber) - return given - } - public static func getCourseDetails(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseDetails__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseDetails(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseDetails__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseDetails).self) - willProduce(stubber) - return given - } - public static func enrollToCourse(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_enrollToCourse__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func enrollToCourse(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_enrollToCourse__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func discovery(page: Parameter) -> Verify { return Verify(method: .m_discovery__page_page(`page`))} - public static func discoveryOffline() -> Verify { return Verify(method: .m_discoveryOffline)} - public static func search(page: Parameter, searchTerm: Parameter) -> Verify { return Verify(method: .m_search__page_pagesearchTerm_searchTerm(`page`, `searchTerm`))} - public static func getLoadedCourseDetails(courseID: Parameter) -> Verify { return Verify(method: .m_getLoadedCourseDetails__courseID_courseID(`courseID`))} - public static func getCourseDetails(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseDetails__courseID_courseID(`courseID`))} - public static func enrollToCourse(courseID: Parameter) -> Verify { return Verify(method: .m_enrollToCourse__courseID_courseID(`courseID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func discovery(page: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_discovery__page_page(`page`), performs: perform) - } - public static func discoveryOffline(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_discoveryOffline, performs: perform) - } - public static func search(page: Parameter, searchTerm: Parameter, perform: @escaping (Int, String) -> Void) -> Perform { - return Perform(method: .m_search__page_pagesearchTerm_searchTerm(`page`, `searchTerm`), performs: perform) - } - public static func getLoadedCourseDetails(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getLoadedCourseDetails__courseID_courseID(`courseID`), performs: perform) - } - public static func getCourseDetails(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseDetails__courseID_courseID(`courseID`), performs: perform) - } - public static func enrollToCourse(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_enrollToCourse__courseID_courseID(`courseID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DownloadManagerProtocol - -open class DownloadManagerProtocolMock: DownloadManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCurrentDownloadTask() -> DownloadDataTask? { - addInvocation(.m_getCurrentDownloadTask) - let perform = methodPerformValue(.m_getCurrentDownloadTask) as? () -> Void - perform?() - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_getCurrentDownloadTask).casted() - } catch { - // do nothing - } - return __value - } - - open func eventPublisher() -> AnyPublisher { - addInvocation(.m_eventPublisher) - let perform = methodPerformValue(.m_eventPublisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_eventPublisher).casted() - } catch { - onFatalFailure("Stub return value not specified for eventPublisher(). Use given") - Failure("Stub return value not specified for eventPublisher(). Use given") - } - return __value - } - - open func addToDownloadQueue(blocks: [CourseBlock]) throws { - addInvocation(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - do { - _ = try methodReturnValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getDownloadTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasks) - let perform = methodPerformValue(.m_getDownloadTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasks(). Use given") - Failure("Stub return value not specified for getDownloadTasks(). Use given") - } - return __value - } - - open func getDownloadTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func cancelDownloading(courseId: String, blocks: [CourseBlock]) throws { - addInvocation(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) as? (String, [CourseBlock]) -> Void - perform?(`courseId`, `blocks`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(task: DownloadDataTask) throws { - addInvocation(.m_cancelDownloading__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_cancelDownloading__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - do { - _ = try methodReturnValue(.m_cancelDownloading__task_task(Parameter.value(`task`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(courseId: String) throws { - addInvocation(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelAllDownloading() throws { - addInvocation(.m_cancelAllDownloading) - let perform = methodPerformValue(.m_cancelAllDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_cancelAllDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func deleteAll() { - addInvocation(.m_deleteAll) - let perform = methodPerformValue(.m_deleteAll) as? () -> Void - perform?() - } - - open func fileUrl(for blockId: String) -> URL? { - addInvocation(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: URL? = nil - do { - __value = try methodReturnValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func resumeDownloading() throws { - addInvocation(.m_resumeDownloading) - let perform = methodPerformValue(.m_resumeDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_resumeDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func isLargeVideosSize(blocks: [CourseBlock]) -> Bool { - addInvocation(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - Failure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - } - return __value - } - - open func removeAppSupportDirectoryUnusedContent() { - addInvocation(.m_removeAppSupportDirectoryUnusedContent) - let perform = methodPerformValue(.m_removeAppSupportDirectoryUnusedContent) as? () -> Void - perform?() - } - - open func delete(blocks: [CourseBlock], courseId: String) { - addInvocation(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) as? ([CourseBlock], String) -> Void - perform?(`blocks`, `courseId`) - } - - open func downloadTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getFreeDiskSpace() -> Int? { - addInvocation(.m_getFreeDiskSpace) - let perform = methodPerformValue(.m_getFreeDiskSpace) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getFreeDiskSpace).casted() - } catch { - // do nothing - } - return __value - } - - - fileprivate enum MethodType { - case m_getCurrentDownloadTask - case m_eventPublisher - case m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>) - case m_getDownloadTasks - case m_getDownloadTasksForCourse__courseId(Parameter) - case m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter, Parameter<[CourseBlock]>) - case m_cancelDownloading__task_task(Parameter) - case m_cancelDownloading__courseId_courseId(Parameter) - case m_cancelAllDownloading - case m_deleteAll - case m_fileUrl__for_blockId(Parameter) - case m_resumeDownloading - case m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>) - case m_removeAppSupportDirectoryUnusedContent - case m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>, Parameter) - case m_downloadTask__for_blockId(Parameter) - case m_getFreeDiskSpace - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCurrentDownloadTask, .m_getCurrentDownloadTask): return .match - - case (.m_eventPublisher, .m_eventPublisher): return .match - - case (.m_addToDownloadQueue__blocks_blocks(let lhsBlocks), .m_addToDownloadQueue__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadTasks, .m_getDownloadTasks): return .match - - case (.m_getDownloadTasksForCourse__courseId(let lhsCourseid), .m_getDownloadTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseIdblocks_blocks(let lhsCourseid, let lhsBlocks), .m_cancelDownloading__courseId_courseIdblocks_blocks(let rhsCourseid, let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__task_task(let lhsTask), .m_cancelDownloading__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseId(let lhsCourseid), .m_cancelDownloading__courseId_courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelAllDownloading, .m_cancelAllDownloading): return .match - - case (.m_deleteAll, .m_deleteAll): return .match - - case (.m_fileUrl__for_blockId(let lhsBlockid), .m_fileUrl__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_resumeDownloading, .m_resumeDownloading): return .match - - case (.m_isLargeVideosSize__blocks_blocks(let lhsBlocks), .m_isLargeVideosSize__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_removeAppSupportDirectoryUnusedContent, .m_removeAppSupportDirectoryUnusedContent): return .match - - case (.m_delete__blocks_blockscourseId_courseId(let lhsBlocks, let lhsCourseid), .m_delete__blocks_blockscourseId_courseId(let rhsBlocks, let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_downloadTask__for_blockId(let lhsBlockid), .m_downloadTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getFreeDiskSpace, .m_getFreeDiskSpace): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_getCurrentDownloadTask: return 0 - case .m_eventPublisher: return 0 - case let .m_addToDownloadQueue__blocks_blocks(p0): return p0.intValue - case .m_getDownloadTasks: return 0 - case let .m_getDownloadTasksForCourse__courseId(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseIdblocks_blocks(p0, p1): return p0.intValue + p1.intValue - case let .m_cancelDownloading__task_task(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseId(p0): return p0.intValue - case .m_cancelAllDownloading: return 0 - case .m_deleteAll: return 0 - case let .m_fileUrl__for_blockId(p0): return p0.intValue - case .m_resumeDownloading: return 0 - case let .m_isLargeVideosSize__blocks_blocks(p0): return p0.intValue - case .m_removeAppSupportDirectoryUnusedContent: return 0 - case let .m_delete__blocks_blockscourseId_courseId(p0, p1): return p0.intValue + p1.intValue - case let .m_downloadTask__for_blockId(p0): return p0.intValue - case .m_getFreeDiskSpace: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_getCurrentDownloadTask: return ".getCurrentDownloadTask()" - case .m_eventPublisher: return ".eventPublisher()" - case .m_addToDownloadQueue__blocks_blocks: return ".addToDownloadQueue(blocks:)" - case .m_getDownloadTasks: return ".getDownloadTasks()" - case .m_getDownloadTasksForCourse__courseId: return ".getDownloadTasksForCourse(_:)" - case .m_cancelDownloading__courseId_courseIdblocks_blocks: return ".cancelDownloading(courseId:blocks:)" - case .m_cancelDownloading__task_task: return ".cancelDownloading(task:)" - case .m_cancelDownloading__courseId_courseId: return ".cancelDownloading(courseId:)" - case .m_cancelAllDownloading: return ".cancelAllDownloading()" - case .m_deleteAll: return ".deleteAll()" - case .m_fileUrl__for_blockId: return ".fileUrl(for:)" - case .m_resumeDownloading: return ".resumeDownloading()" - case .m_isLargeVideosSize__blocks_blocks: return ".isLargeVideosSize(blocks:)" - case .m_removeAppSupportDirectoryUnusedContent: return ".removeAppSupportDirectoryUnusedContent()" - case .m_delete__blocks_blockscourseId_courseId: return ".delete(blocks:courseId:)" - case .m_downloadTask__for_blockId: return ".downloadTask(for:)" - case .m_getFreeDiskSpace: return ".getFreeDiskSpace()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCurrentDownloadTask(willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func eventPublisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func fileUrl(for blockId: Parameter, willReturn: URL?...) -> MethodStub { - return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getFreeDiskSpace(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCurrentDownloadTask(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func eventPublisher(willProduce: (Stubber>) -> Void) -> MethodStub { - let willReturn: [AnyPublisher] = [] - let given: Given = { return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - public static func getDownloadTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func fileUrl(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [URL?] = [] - let given: Given = { return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (URL?).self) - willProduce(stubber) - return given - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func downloadTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getFreeDiskSpace(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(task: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(task: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelAllDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelAllDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func resumeDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resumeDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCurrentDownloadTask() -> Verify { return Verify(method: .m_getCurrentDownloadTask)} - public static func eventPublisher() -> Verify { return Verify(method: .m_eventPublisher)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocks(`blocks`))} - public static func getDownloadTasks() -> Verify { return Verify(method: .m_getDownloadTasks)} - public static func getDownloadTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadTasksForCourse__courseId(`courseId`))} - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`))} - public static func cancelDownloading(task: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__task_task(`task`))} - public static func cancelDownloading(courseId: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseId(`courseId`))} - public static func cancelAllDownloading() -> Verify { return Verify(method: .m_cancelAllDownloading)} - public static func deleteAll() -> Verify { return Verify(method: .m_deleteAll)} - public static func fileUrl(for blockId: Parameter) -> Verify { return Verify(method: .m_fileUrl__for_blockId(`blockId`))} - public static func resumeDownloading() -> Verify { return Verify(method: .m_resumeDownloading)} - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_isLargeVideosSize__blocks_blocks(`blocks`))} - public static func removeAppSupportDirectoryUnusedContent() -> Verify { return Verify(method: .m_removeAppSupportDirectoryUnusedContent)} - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter) -> Verify { return Verify(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`))} - public static func downloadTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadTask__for_blockId(`blockId`))} - public static func getFreeDiskSpace() -> Verify { return Verify(method: .m_getFreeDiskSpace)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCurrentDownloadTask(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getCurrentDownloadTask, performs: perform) - } - public static func eventPublisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_eventPublisher, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), performs: perform) - } - public static func getDownloadTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadTasks, performs: perform) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, perform: @escaping (String, [CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), performs: perform) - } - public static func cancelDownloading(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__task_task(`task`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseId(`courseId`), performs: perform) - } - public static func cancelAllDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_cancelAllDownloading, performs: perform) - } - public static func deleteAll(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAll, performs: perform) - } - public static func fileUrl(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_fileUrl__for_blockId(`blockId`), performs: perform) - } - public static func resumeDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_resumeDownloading, performs: perform) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), performs: perform) - } - public static func removeAppSupportDirectoryUnusedContent(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeAppSupportDirectoryUnusedContent, performs: perform) - } - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter, perform: @escaping ([CourseBlock], String) -> Void) -> Perform { - return Perform(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`), performs: perform) - } - public static func downloadTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadTask__for_blockId(`blockId`), performs: perform) - } - public static func getFreeDiskSpace(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getFreeDiskSpace, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - OfflineSyncInteractorProtocol - -open class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func submitOfflineProgress(courseID: String, blockID: String, data: String) throws -> Bool { - addInvocation(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) - let perform = methodPerformValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) as? (String, String, String) -> Void - perform?(`courseID`, `blockID`, `data`) - var __value: Bool - do { - __value = try methodReturnValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - Failure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter, Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let lhsCourseid, let lhsBlockid, let lhsData), .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let rhsCourseid, let rhsBlockid, let rhsData)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsData, rhs: rhsData, with: matcher), lhsData, rhsData, "data")) - return Matcher.ComparisonResult(results) - } - } - - func intValue() -> Int { - switch self { - case let .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data: return ".submitOfflineProgress(courseID:blockID:data:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter) -> Verify { return Verify(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - diff --git a/Discovery/DiscoveryTests/Generated/DiscoveryMocks.generated.swift b/Discovery/DiscoveryTests/Generated/DiscoveryMocks.generated.swift new file mode 100644 index 000000000..058d227fc --- /dev/null +++ b/Discovery/DiscoveryTests/Generated/DiscoveryMocks.generated.swift @@ -0,0 +1,2599 @@ +/// +/// @Generated by Mockolo +/// + + + +import Alamofire +import Combine +@testable import Core +import CoreData +@testable import Discovery +import Foundation +import OEXFoundation +import SwiftUI +import ZipArchive + + +public final class ConfigProtocolMock: ConfigProtocol, @unchecked Sendable { + public init() { } + public init(baseURL: URL = URL(fileURLWithPath: ""), baseSSOURL: URL = URL(fileURLWithPath: ""), ssoFinishedURL: URL = URL(fileURLWithPath: ""), ssoButtonTitle: [String: Any] = [String: Any](), oAuthClientId: String = "", tokenType: TokenType, feedbackEmail: String = "", appStoreLink: String = "", faq: URL? = nil, platformName: String = "", agreement: AgreementConfig, firebase: FirebaseConfig, facebook: FacebookConfig, microsoft: MicrosoftConfig, google: GoogleConfig, appleSignIn: AppleSignInConfig, features: FeaturesConfig, theme: ThemeConfig, uiComponents: UIComponentsConfig, discovery: DiscoveryConfig, dashboard: DashboardConfig, braze: BrazeConfig, branch: BranchConfig, program: DiscoveryConfig, experimentalFeatures: ExperimentalFeaturesConfig, URIScheme: String = "") { + self.baseURL = baseURL + self.baseSSOURL = baseSSOURL + self.ssoFinishedURL = ssoFinishedURL + self.ssoButtonTitle = ssoButtonTitle + self.oAuthClientId = oAuthClientId + self._tokenType = tokenType + self.feedbackEmail = feedbackEmail + self.appStoreLink = appStoreLink + self.faq = faq + self.platformName = platformName + self._agreement = agreement + self._firebase = firebase + self._facebook = facebook + self._microsoft = microsoft + self._google = google + self._appleSignIn = appleSignIn + self._features = features + self._theme = theme + self._uiComponents = uiComponents + self._discovery = discovery + self._dashboard = dashboard + self._braze = braze + self._branch = branch + self._program = program + self._experimentalFeatures = experimentalFeatures + self.URIScheme = URIScheme + } + + + + public var baseURL: URL = URL(fileURLWithPath: "") + + + public var baseSSOURL: URL = URL(fileURLWithPath: "") + + + public var ssoFinishedURL: URL = URL(fileURLWithPath: "") + + + public var ssoButtonTitle: [String: Any] = [String: Any]() + + + public var oAuthClientId: String = "" + + + private var _tokenType: TokenType! + public var tokenType: TokenType { + get { return _tokenType } + set { _tokenType = newValue } + } + + + public var feedbackEmail: String = "" + + + public var appStoreLink: String = "" + + + public var faq: URL? = nil + + + public var platformName: String = "" + + + private var _agreement: AgreementConfig! + public var agreement: AgreementConfig { + get { return _agreement } + set { _agreement = newValue } + } + + + private var _firebase: FirebaseConfig! + public var firebase: FirebaseConfig { + get { return _firebase } + set { _firebase = newValue } + } + + + private var _facebook: FacebookConfig! + public var facebook: FacebookConfig { + get { return _facebook } + set { _facebook = newValue } + } + + + private var _microsoft: MicrosoftConfig! + public var microsoft: MicrosoftConfig { + get { return _microsoft } + set { _microsoft = newValue } + } + + + private var _google: GoogleConfig! + public var google: GoogleConfig { + get { return _google } + set { _google = newValue } + } + + + private var _appleSignIn: AppleSignInConfig! + public var appleSignIn: AppleSignInConfig { + get { return _appleSignIn } + set { _appleSignIn = newValue } + } + + + private var _features: FeaturesConfig! + public var features: FeaturesConfig { + get { return _features } + set { _features = newValue } + } + + + private var _theme: ThemeConfig! + public var theme: ThemeConfig { + get { return _theme } + set { _theme = newValue } + } + + + private var _uiComponents: UIComponentsConfig! + public var uiComponents: UIComponentsConfig { + get { return _uiComponents } + set { _uiComponents = newValue } + } + + + private var _discovery: DiscoveryConfig! + public var discovery: DiscoveryConfig { + get { return _discovery } + set { _discovery = newValue } + } + + + private var _dashboard: DashboardConfig! + public var dashboard: DashboardConfig { + get { return _dashboard } + set { _dashboard = newValue } + } + + + private var _braze: BrazeConfig! + public var braze: BrazeConfig { + get { return _braze } + set { _braze = newValue } + } + + + private var _branch: BranchConfig! + public var branch: BranchConfig { + get { return _branch } + set { _branch = newValue } + } + + + private var _program: DiscoveryConfig! + public var program: DiscoveryConfig { + get { return _program } + set { _program = newValue } + } + + + private var _experimentalFeatures: ExperimentalFeaturesConfig! + public var experimentalFeatures: ExperimentalFeaturesConfig { + get { return _experimentalFeatures } + set { _experimentalFeatures = newValue } + } + + + public var URIScheme: String = "" +} + +public final class CoreAnalyticsMock: CoreAnalytics { + public init() { } + + + public private(set) var trackEventCallCount = 0 + public var trackEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackEventCallCount += 1 + if let trackEventHandler = trackEventHandler { + trackEventHandler(event, parameters) + } + + } + + public private(set) var trackEventBiValueCallCount = 0 + public var trackEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackEventBiValueCallCount += 1 + if let trackEventBiValueHandler = trackEventBiValueHandler { + trackEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var trackScreenEventCallCount = 0 + public var trackScreenEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackScreenEventCallCount += 1 + if let trackScreenEventHandler = trackScreenEventHandler { + trackScreenEventHandler(event, parameters) + } + + } + + public private(set) var trackScreenEventBiValueCallCount = 0 + public var trackScreenEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackScreenEventBiValueCallCount += 1 + if let trackScreenEventBiValueHandler = trackScreenEventBiValueHandler { + trackScreenEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var appreviewCallCount = 0 + public var appreviewHandler: ((AnalyticsEvent, EventBIValue, String?, Int?) -> ())? + public func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { + appreviewCallCount += 1 + if let appreviewHandler = appreviewHandler { + appreviewHandler(event, biValue, action, rating) + } + + } + + public private(set) var videoQualityChangedCallCount = 0 + public var videoQualityChangedHandler: ((AnalyticsEvent, EventBIValue, String, String) -> ())? + public func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { + videoQualityChangedCallCount += 1 + if let videoQualityChangedHandler = videoQualityChangedHandler { + videoQualityChangedHandler(event, bivalue, value, oldValue) + } + + } +} + +public final class CoreStorageMock: CoreStorage, @unchecked Sendable { + public init() { } + public init(accessToken: String? = nil, refreshToken: String? = nil, pushToken: String? = nil, appleSignFullName: String? = nil, appleSignEmail: String? = nil, cookiesDate: Date? = nil, reviewLastShownVersion: String? = nil, lastReviewDate: Date? = nil, user: DataLayer.User? = nil, userSettings: UserSettings? = nil, resetAppSupportDirectoryUserData: Bool? = nil, useRelativeDates: Bool = false, lastUsedSocialAuth: String? = nil, latestAvailableAppVersion: String? = nil, updateAppRequired: Bool = false) { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.pushToken = pushToken + self.appleSignFullName = appleSignFullName + self.appleSignEmail = appleSignEmail + self.cookiesDate = cookiesDate + self.reviewLastShownVersion = reviewLastShownVersion + self.lastReviewDate = lastReviewDate + self.user = user + self.userSettings = userSettings + self.resetAppSupportDirectoryUserData = resetAppSupportDirectoryUserData + self.useRelativeDates = useRelativeDates + self.lastUsedSocialAuth = lastUsedSocialAuth + self.latestAvailableAppVersion = latestAvailableAppVersion + self.updateAppRequired = updateAppRequired + } + + + public private(set) var accessTokenSetCallCount = 0 + public var accessToken: String? = nil { didSet { accessTokenSetCallCount += 1 } } + + public private(set) var refreshTokenSetCallCount = 0 + public var refreshToken: String? = nil { didSet { refreshTokenSetCallCount += 1 } } + + public private(set) var pushTokenSetCallCount = 0 + public var pushToken: String? = nil { didSet { pushTokenSetCallCount += 1 } } + + public private(set) var appleSignFullNameSetCallCount = 0 + public var appleSignFullName: String? = nil { didSet { appleSignFullNameSetCallCount += 1 } } + + public private(set) var appleSignEmailSetCallCount = 0 + public var appleSignEmail: String? = nil { didSet { appleSignEmailSetCallCount += 1 } } + + public private(set) var cookiesDateSetCallCount = 0 + public var cookiesDate: Date? = nil { didSet { cookiesDateSetCallCount += 1 } } + + public private(set) var reviewLastShownVersionSetCallCount = 0 + public var reviewLastShownVersion: String? = nil { didSet { reviewLastShownVersionSetCallCount += 1 } } + + public private(set) var lastReviewDateSetCallCount = 0 + public var lastReviewDate: Date? = nil { didSet { lastReviewDateSetCallCount += 1 } } + + public private(set) var userSetCallCount = 0 + public var user: DataLayer.User? = nil { didSet { userSetCallCount += 1 } } + + public private(set) var userSettingsSetCallCount = 0 + public var userSettings: UserSettings? = nil { didSet { userSettingsSetCallCount += 1 } } + + public private(set) var resetAppSupportDirectoryUserDataSetCallCount = 0 + public var resetAppSupportDirectoryUserData: Bool? = nil { didSet { resetAppSupportDirectoryUserDataSetCallCount += 1 } } + + public private(set) var useRelativeDatesSetCallCount = 0 + public var useRelativeDates: Bool = false { didSet { useRelativeDatesSetCallCount += 1 } } + + public private(set) var lastUsedSocialAuthSetCallCount = 0 + public var lastUsedSocialAuth: String? = nil { didSet { lastUsedSocialAuthSetCallCount += 1 } } + + public private(set) var latestAvailableAppVersionSetCallCount = 0 + public var latestAvailableAppVersion: String? = nil { didSet { latestAvailableAppVersionSetCallCount += 1 } } + + public private(set) var updateAppRequiredSetCallCount = 0 + public var updateAppRequired: Bool = false { didSet { updateAppRequiredSetCallCount += 1 } } + + private let clearState = MockoloMutex(MockoloHandlerState ()>()) + public var clearCallCount: Int { + return clearState.withLock(\.callCount) + } + public var clearHandler: (@Sendable () -> ())? { + get { clearState.withLock(\.handler) } + set { clearState.withLock { $0.handler = newValue } } + } + public func clear() { + let clearHandler = clearState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearHandler = clearHandler { + clearHandler() + } + + } +} + +public final class AuthInteractorProtocolMock: AuthInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let loginState = MockoloMutex(MockoloHandlerState User>()) + public var loginCallCount: Int { + return loginState.withLock(\.callCount) + } + public var loginHandler: (@Sendable (String, String) async throws -> User)? { + get { loginState.withLock(\.handler) } + set { loginState.withLock { $0.handler = newValue } } + } + public func login(username: String, password: String) async throws -> User { + let loginHandler = loginState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginHandler = loginHandler { + return try await loginHandler(username, password) + } + fatalError("loginHandler returns can't have a default value thus its handler must be set") + } + + private let loginExternalTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginExternalTokenCallCount: Int { + return loginExternalTokenState.withLock(\.callCount) + } + public var loginExternalTokenHandler: (@Sendable (String, String) async throws -> User)? { + get { loginExternalTokenState.withLock(\.handler) } + set { loginExternalTokenState.withLock { $0.handler = newValue } } + } + public func login(externalToken: String, backend: String) async throws -> User { + let loginExternalTokenHandler = loginExternalTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginExternalTokenHandler = loginExternalTokenHandler { + return try await loginExternalTokenHandler(externalToken, backend) + } + fatalError("loginExternalTokenHandler returns can't have a default value thus its handler must be set") + } + + private let loginSsoTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginSsoTokenCallCount: Int { + return loginSsoTokenState.withLock(\.callCount) + } + public var loginSsoTokenHandler: (@Sendable (String) async throws -> User)? { + get { loginSsoTokenState.withLock(\.handler) } + set { loginSsoTokenState.withLock { $0.handler = newValue } } + } + public func login(ssoToken: String) async throws -> User { + let loginSsoTokenHandler = loginSsoTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginSsoTokenHandler = loginSsoTokenHandler { + return try await loginSsoTokenHandler(ssoToken) + } + fatalError("loginSsoTokenHandler returns can't have a default value thus its handler must be set") + } + + private let resetPasswordState = MockoloMutex(MockoloHandlerState ResetPassword>()) + public var resetPasswordCallCount: Int { + return resetPasswordState.withLock(\.callCount) + } + public var resetPasswordHandler: (@Sendable (String) async throws -> ResetPassword)? { + get { resetPasswordState.withLock(\.handler) } + set { resetPasswordState.withLock { $0.handler = newValue } } + } + public func resetPassword(email: String) async throws -> ResetPassword { + let resetPasswordHandler = resetPasswordState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resetPasswordHandler = resetPasswordHandler { + return try await resetPasswordHandler(email) + } + fatalError("resetPasswordHandler returns can't have a default value thus its handler must be set") + } + + private let getCookiesState = MockoloMutex(MockoloHandlerState ()>()) + public var getCookiesCallCount: Int { + return getCookiesState.withLock(\.callCount) + } + public var getCookiesHandler: (@Sendable (Bool) async throws -> ())? { + get { getCookiesState.withLock(\.handler) } + set { getCookiesState.withLock { $0.handler = newValue } } + } + public func getCookies(force: Bool) async throws { + let getCookiesHandler = getCookiesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCookiesHandler = getCookiesHandler { + try await getCookiesHandler(force) + } + + } + + private let getRegistrationFieldsState = MockoloMutex(MockoloHandlerState [PickerFields]>()) + public var getRegistrationFieldsCallCount: Int { + return getRegistrationFieldsState.withLock(\.callCount) + } + public var getRegistrationFieldsHandler: (@Sendable () async throws -> [PickerFields])? { + get { getRegistrationFieldsState.withLock(\.handler) } + set { getRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func getRegistrationFields() async throws -> [PickerFields] { + let getRegistrationFieldsHandler = getRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getRegistrationFieldsHandler = getRegistrationFieldsHandler { + return try await getRegistrationFieldsHandler() + } + return [PickerFields]() + } + + private let registerUserState = MockoloMutex(MockoloHandlerState User>()) + public var registerUserCallCount: Int { + return registerUserState.withLock(\.callCount) + } + public var registerUserHandler: (@Sendable ([String: String], Bool) async throws -> User)? { + get { registerUserState.withLock(\.handler) } + set { registerUserState.withLock { $0.handler = newValue } } + } + public func registerUser(fields: [String: String], isSocial: Bool) async throws -> User { + let registerUserHandler = registerUserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let registerUserHandler = registerUserHandler { + return try await registerUserHandler(fields, isSocial) + } + fatalError("registerUserHandler returns can't have a default value thus its handler must be set") + } + + private let validateRegistrationFieldsState = MockoloMutex(MockoloHandlerState [String: String]>()) + public var validateRegistrationFieldsCallCount: Int { + return validateRegistrationFieldsState.withLock(\.callCount) + } + public var validateRegistrationFieldsHandler: (@Sendable ([String: String]) async throws -> [String: String])? { + get { validateRegistrationFieldsState.withLock(\.handler) } + set { validateRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func validateRegistrationFields(fields: [String: String]) async throws -> [String: String] { + let validateRegistrationFieldsHandler = validateRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let validateRegistrationFieldsHandler = validateRegistrationFieldsHandler { + return try await validateRegistrationFieldsHandler(fields) + } + return [String: String]() + } +} + +public final class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let submitOfflineProgressState = MockoloMutex(MockoloHandlerState Bool>()) + public var submitOfflineProgressCallCount: Int { + return submitOfflineProgressState.withLock(\.callCount) + } + public var submitOfflineProgressHandler: (@Sendable (String, String, String) async throws -> Bool)? { + get { submitOfflineProgressState.withLock(\.handler) } + set { submitOfflineProgressState.withLock { $0.handler = newValue } } + } + public func submitOfflineProgress(courseID: String, blockID: String, data: String) async throws -> Bool { + let submitOfflineProgressHandler = submitOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let submitOfflineProgressHandler = submitOfflineProgressHandler { + return try await submitOfflineProgressHandler(courseID, blockID, data) + } + return false + } +} + +public final class WebviewCookiesUpdateProtocolMock: WebviewCookiesUpdateProtocol { + public init() { } + public init(authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock(), cookiesReady: Bool = false, updatingCookies: Bool = false, errorMessage: String? = nil) { + self.authInteractor = authInteractor + self.cookiesReady = cookiesReady + self.updatingCookies = updatingCookies + self.errorMessage = errorMessage + } + + + + public var authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock() + + public private(set) var cookiesReadySetCallCount = 0 + public var cookiesReady: Bool = false { didSet { cookiesReadySetCallCount += 1 } } + + public private(set) var updatingCookiesSetCallCount = 0 + public var updatingCookies: Bool = false { didSet { updatingCookiesSetCallCount += 1 } } + + public private(set) var errorMessageSetCallCount = 0 + public var errorMessage: String? = nil { didSet { errorMessageSetCallCount += 1 } } + + public private(set) var updateCookiesCallCount = 0 + public var updateCookiesHandler: ((Bool, Int) async -> ())? + public func updateCookies(force: Bool, retryCount: Int) async { + updateCookiesCallCount += 1 + if let updateCookiesHandler = updateCookiesHandler { + await updateCookiesHandler(force, retryCount) + } + + } +} + +public final class BaseRouterMock: BaseRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class CalendarManagerProtocolMock: CalendarManagerProtocol, @unchecked Sendable { + public init() { } + + + private let createCalendarIfNeededState = MockoloMutex(MockoloHandlerState ()>()) + public var createCalendarIfNeededCallCount: Int { + return createCalendarIfNeededState.withLock(\.callCount) + } + public var createCalendarIfNeededHandler: (@Sendable () -> ())? { + get { createCalendarIfNeededState.withLock(\.handler) } + set { createCalendarIfNeededState.withLock { $0.handler = newValue } } + } + public func createCalendarIfNeeded() { + let createCalendarIfNeededHandler = createCalendarIfNeededState.withLock { state in + state.callCount += 1 + return state.handler + } + if let createCalendarIfNeededHandler = createCalendarIfNeededHandler { + createCalendarIfNeededHandler() + } + + } + + private let filterCoursesBySelectedState = MockoloMutex(MockoloHandlerState [CourseForSync]>()) + public var filterCoursesBySelectedCallCount: Int { + return filterCoursesBySelectedState.withLock(\.callCount) + } + public var filterCoursesBySelectedHandler: (@Sendable ([CourseForSync]) async -> [CourseForSync])? { + get { filterCoursesBySelectedState.withLock(\.handler) } + set { filterCoursesBySelectedState.withLock { $0.handler = newValue } } + } + public func filterCoursesBySelected(fetchedCourses: [CourseForSync]) async -> [CourseForSync] { + let filterCoursesBySelectedHandler = filterCoursesBySelectedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let filterCoursesBySelectedHandler = filterCoursesBySelectedHandler { + return await filterCoursesBySelectedHandler(fetchedCourses) + } + return [CourseForSync]() + } + + private let removeOldCalendarState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOldCalendarCallCount: Int { + return removeOldCalendarState.withLock(\.callCount) + } + public var removeOldCalendarHandler: (@Sendable () -> ())? { + get { removeOldCalendarState.withLock(\.handler) } + set { removeOldCalendarState.withLock { $0.handler = newValue } } + } + public func removeOldCalendar() { + let removeOldCalendarHandler = removeOldCalendarState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOldCalendarHandler = removeOldCalendarHandler { + removeOldCalendarHandler() + } + + } + + private let removeOutdatedEventsState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOutdatedEventsCallCount: Int { + return removeOutdatedEventsState.withLock(\.callCount) + } + public var removeOutdatedEventsHandler: (@Sendable (String) async -> ())? { + get { removeOutdatedEventsState.withLock(\.handler) } + set { removeOutdatedEventsState.withLock { $0.handler = newValue } } + } + public func removeOutdatedEvents(courseID: String) async { + let removeOutdatedEventsHandler = removeOutdatedEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOutdatedEventsHandler = removeOutdatedEventsHandler { + await removeOutdatedEventsHandler(courseID) + } + + } + + private let syncCourseState = MockoloMutex(MockoloHandlerState ()>()) + public var syncCourseCallCount: Int { + return syncCourseState.withLock(\.callCount) + } + public var syncCourseHandler: (@Sendable (String, String, CourseDates) async -> ())? { + get { syncCourseState.withLock(\.handler) } + set { syncCourseState.withLock { $0.handler = newValue } } + } + public func syncCourse(courseID: String, courseName: String, dates: CourseDates) async { + let syncCourseHandler = syncCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let syncCourseHandler = syncCourseHandler { + await syncCourseHandler(courseID, courseName, dates) + } + + } + + private let requestAccessState = MockoloMutex(MockoloHandlerState Bool>()) + public var requestAccessCallCount: Int { + return requestAccessState.withLock(\.callCount) + } + public var requestAccessHandler: (@Sendable () async -> Bool)? { + get { requestAccessState.withLock(\.handler) } + set { requestAccessState.withLock { $0.handler = newValue } } + } + public func requestAccess() async -> Bool { + let requestAccessHandler = requestAccessState.withLock { state in + state.callCount += 1 + return state.handler + } + if let requestAccessHandler = requestAccessHandler { + return await requestAccessHandler() + } + return false + } + + private let courseStatusState = MockoloMutex(MockoloHandlerState SyncStatus>()) + public var courseStatusCallCount: Int { + return courseStatusState.withLock(\.callCount) + } + public var courseStatusHandler: (@Sendable (String) async -> SyncStatus)? { + get { courseStatusState.withLock(\.handler) } + set { courseStatusState.withLock { $0.handler = newValue } } + } + public func courseStatus(courseID: String) async -> SyncStatus { + let courseStatusHandler = courseStatusState.withLock { state in + state.callCount += 1 + return state.handler + } + if let courseStatusHandler = courseStatusHandler { + return await courseStatusHandler(courseID) + } + fatalError("courseStatusHandler returns can't have a default value thus its handler must be set") + } + + private let clearAllDataState = MockoloMutex(MockoloHandlerState ()>()) + public var clearAllDataCallCount: Int { + return clearAllDataState.withLock(\.callCount) + } + public var clearAllDataHandler: (@Sendable (Bool) async -> ())? { + get { clearAllDataState.withLock(\.handler) } + set { clearAllDataState.withLock { $0.handler = newValue } } + } + public func clearAllData(removeCalendar: Bool) async { + let clearAllDataHandler = clearAllDataState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearAllDataHandler = clearAllDataHandler { + await clearAllDataHandler(removeCalendar) + } + + } + + private let isDatesChangedState = MockoloMutex(MockoloHandlerState Bool>()) + public var isDatesChangedCallCount: Int { + return isDatesChangedState.withLock(\.callCount) + } + public var isDatesChangedHandler: (@Sendable (String, String) async -> Bool)? { + get { isDatesChangedState.withLock(\.handler) } + set { isDatesChangedState.withLock { $0.handler = newValue } } + } + public func isDatesChanged(courseID: String, checksum: String) async -> Bool { + let isDatesChangedHandler = isDatesChangedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isDatesChangedHandler = isDatesChangedHandler { + return await isDatesChangedHandler(courseID, checksum) + } + return false + } +} + +public final class CorePersistenceProtocolMock: CorePersistenceProtocol, @unchecked Sendable { + public init() { } + + + private let setState = MockoloMutex(MockoloHandlerState ()>()) + public var setCallCount: Int { + return setState.withLock(\.callCount) + } + public var setHandler: (@Sendable (Int) -> ())? { + get { setState.withLock(\.handler) } + set { setState.withLock { $0.handler = newValue } } + } + public func set(userId: Int) { + let setHandler = setState.withLock { state in + state.callCount += 1 + return state.handler + } + if let setHandler = setHandler { + setHandler(userId) + } + + } + + private let getUserIDState = MockoloMutex(MockoloHandlerState Int?>()) + public var getUserIDCallCount: Int { + return getUserIDState.withLock(\.callCount) + } + public var getUserIDHandler: (@Sendable () -> Int?)? { + get { getUserIDState.withLock(\.handler) } + set { getUserIDState.withLock { $0.handler = newValue } } + } + public func getUserID() -> Int? { + let getUserIDHandler = getUserIDState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getUserIDHandler = getUserIDHandler { + return getUserIDHandler() + } + return nil + } + + private let publisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var publisherCallCount: Int { + return publisherState.withLock(\.callCount) + } + public var publisherHandler: (@Sendable () throws -> AnyPublisher)? { + get { publisherState.withLock(\.handler) } + set { publisherState.withLock { $0.handler = newValue } } + } + public func publisher() throws -> AnyPublisher { + let publisherHandler = publisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let publisherHandler = publisherHandler { + return try publisherHandler() + } + fatalError("publisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([DownloadDataTask]) -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(tasks: [DownloadDataTask]) { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + addToDownloadQueueHandler(tasks) + } + + } + + private let saveOfflineProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var saveOfflineProgressCallCount: Int { + return saveOfflineProgressState.withLock(\.callCount) + } + public var saveOfflineProgressHandler: (@Sendable (OfflineProgress) async -> ())? { + get { saveOfflineProgressState.withLock(\.handler) } + set { saveOfflineProgressState.withLock { $0.handler = newValue } } + } + public func saveOfflineProgress(progress: OfflineProgress) async { + let saveOfflineProgressHandler = saveOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveOfflineProgressHandler = saveOfflineProgressHandler { + await saveOfflineProgressHandler(progress) + } + + } + + private let loadProgressState = MockoloMutex(MockoloHandlerState OfflineProgress?>()) + public var loadProgressCallCount: Int { + return loadProgressState.withLock(\.callCount) + } + public var loadProgressHandler: (@Sendable (String) async -> OfflineProgress?)? { + get { loadProgressState.withLock(\.handler) } + set { loadProgressState.withLock { $0.handler = newValue } } + } + public func loadProgress(for blockID: String) async -> OfflineProgress? { + let loadProgressHandler = loadProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadProgressHandler = loadProgressHandler { + return await loadProgressHandler(blockID) + } + return nil + } + + private let loadAllOfflineProgressState = MockoloMutex(MockoloHandlerState [OfflineProgress]>()) + public var loadAllOfflineProgressCallCount: Int { + return loadAllOfflineProgressState.withLock(\.callCount) + } + public var loadAllOfflineProgressHandler: (@Sendable () async -> [OfflineProgress])? { + get { loadAllOfflineProgressState.withLock(\.handler) } + set { loadAllOfflineProgressState.withLock { $0.handler = newValue } } + } + public func loadAllOfflineProgress() async -> [OfflineProgress] { + let loadAllOfflineProgressHandler = loadAllOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadAllOfflineProgressHandler = loadAllOfflineProgressHandler { + return await loadAllOfflineProgressHandler() + } + return [OfflineProgress]() + } + + private let deleteProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteProgressCallCount: Int { + return deleteProgressState.withLock(\.callCount) + } + public var deleteProgressHandler: (@Sendable (String) async -> ())? { + get { deleteProgressState.withLock(\.handler) } + set { deleteProgressState.withLock { $0.handler = newValue } } + } + public func deleteProgress(for blockID: String) async { + let deleteProgressHandler = deleteProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteProgressHandler = deleteProgressHandler { + await deleteProgressHandler(blockID) + } + + } + + private let deleteAllProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllProgressCallCount: Int { + return deleteAllProgressState.withLock(\.callCount) + } + public var deleteAllProgressHandler: (@Sendable () async -> ())? { + get { deleteAllProgressState.withLock(\.handler) } + set { deleteAllProgressState.withLock { $0.handler = newValue } } + } + public func deleteAllProgress() async { + let deleteAllProgressHandler = deleteAllProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllProgressHandler = deleteAllProgressHandler { + await deleteAllProgressHandler() + } + + } + + private let addToDownloadQueueBlocksState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueBlocksCallCount: Int { + return addToDownloadQueueBlocksState.withLock(\.callCount) + } + public var addToDownloadQueueBlocksHandler: (@Sendable ([CourseBlock], DownloadQuality) -> ())? { + get { addToDownloadQueueBlocksState.withLock(\.handler) } + set { addToDownloadQueueBlocksState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { + let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksHandler { + addToDownloadQueueBlocksHandler(blocks, downloadQuality) + } + + } + + private let updateTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var updateTaskCallCount: Int { + return updateTaskState.withLock(\.callCount) + } + public var updateTaskHandler: (@Sendable (DownloadDataTask) -> ())? { + get { updateTaskState.withLock(\.handler) } + set { updateTaskState.withLock { $0.handler = newValue } } + } + public func updateTask(task: DownloadDataTask) { + let updateTaskHandler = updateTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateTaskHandler = updateTaskHandler { + updateTaskHandler(task) + } + + } + + private let downloadDataTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadDataTaskCallCount: Int { + return downloadDataTaskState.withLock(\.callCount) + } + public var downloadDataTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadDataTaskState.withLock(\.handler) } + set { downloadDataTaskState.withLock { $0.handler = newValue } } + } + public func downloadDataTask(for blockId: String) async -> DownloadDataTask? { + let downloadDataTaskHandler = downloadDataTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadDataTaskHandler = downloadDataTaskHandler { + return await downloadDataTaskHandler(blockId) + } + return nil + } + + private let getDownloadDataTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksCallCount: Int { + return getDownloadDataTasksState.withLock(\.callCount) + } + public var getDownloadDataTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadDataTasksState.withLock(\.handler) } + set { getDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasks() async -> [DownloadDataTask] { + let getDownloadDataTasksHandler = getDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksHandler = getDownloadDataTasksHandler { + return await getDownloadDataTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadDataTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksForCourseCallCount: Int { + return getDownloadDataTasksForCourseState.withLock(\.callCount) + } + public var getDownloadDataTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadDataTasksForCourseState.withLock(\.handler) } + set { getDownloadDataTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseHandler { + return await getDownloadDataTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let deleteDownloadDataTasksState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteDownloadDataTasksCallCount: Int { + return deleteDownloadDataTasksState.withLock(\.callCount) + } + public var deleteDownloadDataTasksHandler: (@Sendable ([String]) -> ())? { + get { deleteDownloadDataTasksState.withLock(\.handler) } + set { deleteDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func deleteDownloadDataTasks(ids: [String]) { + let deleteDownloadDataTasksHandler = deleteDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteDownloadDataTasksHandler = deleteDownloadDataTasksHandler { + deleteDownloadDataTasksHandler(ids) + } + + } +} + +public final class DiscoveryRouterMock: DiscoveryRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let showCourseDetaisState = MockoloMutex(MockoloHandlerState ()>()) + public var showCourseDetaisCallCount: Int { + return showCourseDetaisState.withLock(\.callCount) + } + public var showCourseDetaisHandler: (@Sendable (String, String) -> ())? { + get { showCourseDetaisState.withLock(\.handler) } + set { showCourseDetaisState.withLock { $0.handler = newValue } } + } + public func showCourseDetais(courseID: String, title: String) { + let showCourseDetaisHandler = showCourseDetaisState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showCourseDetaisHandler = showCourseDetaisHandler { + showCourseDetaisHandler(courseID, title) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let showWebDiscoveryDetailsState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebDiscoveryDetailsCallCount: Int { + return showWebDiscoveryDetailsState.withLock(\.callCount) + } + public var showWebDiscoveryDetailsHandler: (@Sendable (String, DiscoveryWebviewType, LogistrationSourceScreen) -> ())? { + get { showWebDiscoveryDetailsState.withLock(\.handler) } + set { showWebDiscoveryDetailsState.withLock { $0.handler = newValue } } + } + public func showWebDiscoveryDetails(pathID: String, discoveryType: DiscoveryWebviewType, sourceScreen: LogistrationSourceScreen) { + let showWebDiscoveryDetailsHandler = showWebDiscoveryDetailsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebDiscoveryDetailsHandler = showWebDiscoveryDetailsHandler { + showWebDiscoveryDetailsHandler(pathID, discoveryType, sourceScreen) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showUpdateRequiredViewState = MockoloMutex(MockoloHandlerState ()>()) + public var showUpdateRequiredViewCallCount: Int { + return showUpdateRequiredViewState.withLock(\.callCount) + } + public var showUpdateRequiredViewHandler: (@Sendable (Bool) -> ())? { + get { showUpdateRequiredViewState.withLock(\.handler) } + set { showUpdateRequiredViewState.withLock { $0.handler = newValue } } + } + public func showUpdateRequiredView(showAccountLink: Bool) { + let showUpdateRequiredViewHandler = showUpdateRequiredViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showUpdateRequiredViewHandler = showUpdateRequiredViewHandler { + showUpdateRequiredViewHandler(showAccountLink) + } + + } + + private let showUpdateRecomendedViewState = MockoloMutex(MockoloHandlerState ()>()) + public var showUpdateRecomendedViewCallCount: Int { + return showUpdateRecomendedViewState.withLock(\.callCount) + } + public var showUpdateRecomendedViewHandler: (@Sendable () -> ())? { + get { showUpdateRecomendedViewState.withLock(\.handler) } + set { showUpdateRecomendedViewState.withLock { $0.handler = newValue } } + } + public func showUpdateRecomendedView() { + let showUpdateRecomendedViewHandler = showUpdateRecomendedViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showUpdateRecomendedViewHandler = showUpdateRecomendedViewHandler { + showUpdateRecomendedViewHandler() + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showDiscoverySearchState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoverySearchCallCount: Int { + return showDiscoverySearchState.withLock(\.callCount) + } + public var showDiscoverySearchHandler: (@Sendable (String?) -> ())? { + get { showDiscoverySearchState.withLock(\.handler) } + set { showDiscoverySearchState.withLock { $0.handler = newValue } } + } + public func showDiscoverySearch(searchQuery: String?) { + let showDiscoverySearchHandler = showDiscoverySearchState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoverySearchHandler = showDiscoverySearchHandler { + showDiscoverySearchHandler(searchQuery) + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showCourseScreensState = MockoloMutex(MockoloHandlerState ()>()) + public var showCourseScreensCallCount: Int { + return showCourseScreensState.withLock(\.callCount) + } + public var showCourseScreensHandler: (@Sendable (String, Bool?, Date?, Date?, Date?, Date?, String, String?, Bool, String?) -> ())? { + get { showCourseScreensState.withLock(\.handler) } + set { showCourseScreensState.withLock { $0.handler = newValue } } + } + public func showCourseScreens(courseID: String, hasAccess: Bool?, courseStart: Date?, courseEnd: Date?, enrollmentStart: Date?, enrollmentEnd: Date?, title: String, courseRawImage: String?, showDates: Bool, lastVisitedBlockID: String?) { + let showCourseScreensHandler = showCourseScreensState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showCourseScreensHandler = showCourseScreensHandler { + showCourseScreensHandler(courseID, hasAccess, courseStart, courseEnd, enrollmentStart, enrollmentEnd, title, courseRawImage, showDates, lastVisitedBlockID) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let showWebProgramDetailsState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebProgramDetailsCallCount: Int { + return showWebProgramDetailsState.withLock(\.callCount) + } + public var showWebProgramDetailsHandler: (@Sendable (String, ProgramViewType) -> ())? { + get { showWebProgramDetailsState.withLock(\.handler) } + set { showWebProgramDetailsState.withLock { $0.handler = newValue } } + } + public func showWebProgramDetails(pathID: String, viewType: ProgramViewType) { + let showWebProgramDetailsHandler = showWebProgramDetailsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebProgramDetailsHandler = showWebProgramDetailsHandler { + showWebProgramDetailsHandler(pathID, viewType) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseBlocksCallCount: Int { + return getCourseBlocksState.withLock(\.callCount) + } + public var getCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getCourseBlocksState.withLock(\.handler) } + set { getCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseBlocks(courseID: String) async throws -> CourseStructure { + let getCourseBlocksHandler = getCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseBlocksHandler = getCourseBlocksHandler { + return try await getCourseBlocksHandler(courseID) + } + fatalError("getCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getLoadedCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getLoadedCourseBlocksCallCount: Int { + return getLoadedCourseBlocksState.withLock(\.callCount) + } + public var getLoadedCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getLoadedCourseBlocksState.withLock(\.handler) } + set { getLoadedCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure { + let getLoadedCourseBlocksHandler = getLoadedCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseBlocksHandler = getLoadedCourseBlocksHandler { + return try await getLoadedCourseBlocksHandler(courseID) + } + fatalError("getLoadedCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let shiftDueDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var shiftDueDatesCallCount: Int { + return shiftDueDatesState.withLock(\.callCount) + } + public var shiftDueDatesHandler: (@Sendable (String) async throws -> ())? { + get { shiftDueDatesState.withLock(\.handler) } + set { shiftDueDatesState.withLock { $0.handler = newValue } } + } + public func shiftDueDates(courseID: String) async throws { + let shiftDueDatesHandler = shiftDueDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let shiftDueDatesHandler = shiftDueDatesHandler { + try await shiftDueDatesHandler(courseID) + } + + } +} + +public final class DiscoveryInteractorProtocolMock: DiscoveryInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let discoveryState = MockoloMutex(MockoloHandlerState [CourseItem]>()) + public var discoveryCallCount: Int { + return discoveryState.withLock(\.callCount) + } + public var discoveryHandler: (@Sendable (Int) async throws -> [CourseItem])? { + get { discoveryState.withLock(\.handler) } + set { discoveryState.withLock { $0.handler = newValue } } + } + public func discovery(page: Int) async throws -> [CourseItem] { + let discoveryHandler = discoveryState.withLock { state in + state.callCount += 1 + return state.handler + } + if let discoveryHandler = discoveryHandler { + return try await discoveryHandler(page) + } + return [CourseItem]() + } + + private let discoveryOfflineState = MockoloMutex(MockoloHandlerState [CourseItem]>()) + public var discoveryOfflineCallCount: Int { + return discoveryOfflineState.withLock(\.callCount) + } + public var discoveryOfflineHandler: (@Sendable () async throws -> [CourseItem])? { + get { discoveryOfflineState.withLock(\.handler) } + set { discoveryOfflineState.withLock { $0.handler = newValue } } + } + public func discoveryOffline() async throws -> [CourseItem] { + let discoveryOfflineHandler = discoveryOfflineState.withLock { state in + state.callCount += 1 + return state.handler + } + if let discoveryOfflineHandler = discoveryOfflineHandler { + return try await discoveryOfflineHandler() + } + return [CourseItem]() + } + + private let searchState = MockoloMutex(MockoloHandlerState [CourseItem]>()) + public var searchCallCount: Int { + return searchState.withLock(\.callCount) + } + public var searchHandler: (@Sendable (Int, String) async throws -> [CourseItem])? { + get { searchState.withLock(\.handler) } + set { searchState.withLock { $0.handler = newValue } } + } + public func search(page: Int, searchTerm: String) async throws -> [CourseItem] { + let searchHandler = searchState.withLock { state in + state.callCount += 1 + return state.handler + } + if let searchHandler = searchHandler { + return try await searchHandler(page, searchTerm) + } + return [CourseItem]() + } + + private let getLoadedCourseDetailsState = MockoloMutex(MockoloHandlerState CourseDetails>()) + public var getLoadedCourseDetailsCallCount: Int { + return getLoadedCourseDetailsState.withLock(\.callCount) + } + public var getLoadedCourseDetailsHandler: (@Sendable (String) async throws -> CourseDetails)? { + get { getLoadedCourseDetailsState.withLock(\.handler) } + set { getLoadedCourseDetailsState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseDetails(courseID: String) async throws -> CourseDetails { + let getLoadedCourseDetailsHandler = getLoadedCourseDetailsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseDetailsHandler = getLoadedCourseDetailsHandler { + return try await getLoadedCourseDetailsHandler(courseID) + } + fatalError("getLoadedCourseDetailsHandler returns can't have a default value thus its handler must be set") + } + + private let getCourseDetailsState = MockoloMutex(MockoloHandlerState CourseDetails>()) + public var getCourseDetailsCallCount: Int { + return getCourseDetailsState.withLock(\.callCount) + } + public var getCourseDetailsHandler: (@Sendable (String) async throws -> CourseDetails)? { + get { getCourseDetailsState.withLock(\.handler) } + set { getCourseDetailsState.withLock { $0.handler = newValue } } + } + public func getCourseDetails(courseID: String) async throws -> CourseDetails { + let getCourseDetailsHandler = getCourseDetailsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDetailsHandler = getCourseDetailsHandler { + return try await getCourseDetailsHandler(courseID) + } + fatalError("getCourseDetailsHandler returns can't have a default value thus its handler must be set") + } + + private let enrollToCourseState = MockoloMutex(MockoloHandlerState Bool>()) + public var enrollToCourseCallCount: Int { + return enrollToCourseState.withLock(\.callCount) + } + public var enrollToCourseHandler: (@Sendable (String) async throws -> Bool)? { + get { enrollToCourseState.withLock(\.handler) } + set { enrollToCourseState.withLock { $0.handler = newValue } } + } + public func enrollToCourse(courseID: String) async throws -> Bool { + let enrollToCourseHandler = enrollToCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let enrollToCourseHandler = enrollToCourseHandler { + return try await enrollToCourseHandler(courseID) + } + return false + } +} + +public final class DiscoveryAnalyticsMock: DiscoveryAnalytics { + public init() { } + + + public private(set) var discoverySearchBarClickedCallCount = 0 + public var discoverySearchBarClickedHandler: (() -> ())? + public func discoverySearchBarClicked() { + discoverySearchBarClickedCallCount += 1 + if let discoverySearchBarClickedHandler = discoverySearchBarClickedHandler { + discoverySearchBarClickedHandler() + } + + } + + public private(set) var discoveryCoursesSearchCallCount = 0 + public var discoveryCoursesSearchHandler: ((String, Int) -> ())? + public func discoveryCoursesSearch(label: String, coursesCount: Int) { + discoveryCoursesSearchCallCount += 1 + if let discoveryCoursesSearchHandler = discoveryCoursesSearchHandler { + discoveryCoursesSearchHandler(label, coursesCount) + } + + } + + public private(set) var discoveryCourseClickedCallCount = 0 + public var discoveryCourseClickedHandler: ((String, String) -> ())? + public func discoveryCourseClicked(courseID: String, courseName: String) { + discoveryCourseClickedCallCount += 1 + if let discoveryCourseClickedHandler = discoveryCourseClickedHandler { + discoveryCourseClickedHandler(courseID, courseName) + } + + } + + public private(set) var viewCourseClickedCallCount = 0 + public var viewCourseClickedHandler: ((String, String) -> ())? + public func viewCourseClicked(courseId: String, courseName: String) { + viewCourseClickedCallCount += 1 + if let viewCourseClickedHandler = viewCourseClickedHandler { + viewCourseClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseEnrollClickedCallCount = 0 + public var courseEnrollClickedHandler: ((String, String) -> ())? + public func courseEnrollClicked(courseId: String, courseName: String) { + courseEnrollClickedCallCount += 1 + if let courseEnrollClickedHandler = courseEnrollClickedHandler { + courseEnrollClickedHandler(courseId, courseName) + } + + } + + public private(set) var courseEnrollSuccessCallCount = 0 + public var courseEnrollSuccessHandler: ((String, String) -> ())? + public func courseEnrollSuccess(courseId: String, courseName: String) { + courseEnrollSuccessCallCount += 1 + if let courseEnrollSuccessHandler = courseEnrollSuccessHandler { + courseEnrollSuccessHandler(courseId, courseName) + } + + } + + public private(set) var externalLinkOpenCallCount = 0 + public var externalLinkOpenHandler: ((String, String) -> ())? + public func externalLinkOpen(url: String, screen: String) { + externalLinkOpenCallCount += 1 + if let externalLinkOpenHandler = externalLinkOpenHandler { + externalLinkOpenHandler(url, screen) + } + + } + + public private(set) var externalLinkOpenActionCallCount = 0 + public var externalLinkOpenActionHandler: ((String, String, String) -> ())? + public func externalLinkOpenAction(url: String, screen: String, action: String) { + externalLinkOpenActionCallCount += 1 + if let externalLinkOpenActionHandler = externalLinkOpenActionHandler { + externalLinkOpenActionHandler(url, screen, action) + } + + } + + public private(set) var discoveryScreenEventCallCount = 0 + public var discoveryScreenEventHandler: ((AnalyticsEvent, EventBIValue) -> ())? + public func discoveryScreenEvent(event: AnalyticsEvent, biValue: EventBIValue) { + discoveryScreenEventCallCount += 1 + if let discoveryScreenEventHandler = discoveryScreenEventHandler { + discoveryScreenEventHandler(event, biValue) + } + + } +} + +public final class DiscoveryRepositoryProtocolMock: DiscoveryRepositoryProtocol, @unchecked Sendable { + public init() { } + + + private let getDiscoveryState = MockoloMutex(MockoloHandlerState [CourseItem]>()) + public var getDiscoveryCallCount: Int { + return getDiscoveryState.withLock(\.callCount) + } + public var getDiscoveryHandler: (@Sendable (Int) async throws -> [CourseItem])? { + get { getDiscoveryState.withLock(\.handler) } + set { getDiscoveryState.withLock { $0.handler = newValue } } + } + public func getDiscovery(page: Int) async throws -> [CourseItem] { + let getDiscoveryHandler = getDiscoveryState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDiscoveryHandler = getDiscoveryHandler { + return try await getDiscoveryHandler(page) + } + return [CourseItem]() + } + + private let searchCoursesState = MockoloMutex(MockoloHandlerState [CourseItem]>()) + public var searchCoursesCallCount: Int { + return searchCoursesState.withLock(\.callCount) + } + public var searchCoursesHandler: (@Sendable (Int, String) async throws -> [CourseItem])? { + get { searchCoursesState.withLock(\.handler) } + set { searchCoursesState.withLock { $0.handler = newValue } } + } + public func searchCourses(page: Int, searchTerm: String) async throws -> [CourseItem] { + let searchCoursesHandler = searchCoursesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let searchCoursesHandler = searchCoursesHandler { + return try await searchCoursesHandler(page, searchTerm) + } + return [CourseItem]() + } + + private let getDiscoveryOfflineState = MockoloMutex(MockoloHandlerState [CourseItem]>()) + public var getDiscoveryOfflineCallCount: Int { + return getDiscoveryOfflineState.withLock(\.callCount) + } + public var getDiscoveryOfflineHandler: (@Sendable () async throws -> [CourseItem])? { + get { getDiscoveryOfflineState.withLock(\.handler) } + set { getDiscoveryOfflineState.withLock { $0.handler = newValue } } + } + public func getDiscoveryOffline() async throws -> [CourseItem] { + let getDiscoveryOfflineHandler = getDiscoveryOfflineState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDiscoveryOfflineHandler = getDiscoveryOfflineHandler { + return try await getDiscoveryOfflineHandler() + } + return [CourseItem]() + } + + private let getCourseDetailsState = MockoloMutex(MockoloHandlerState CourseDetails>()) + public var getCourseDetailsCallCount: Int { + return getCourseDetailsState.withLock(\.callCount) + } + public var getCourseDetailsHandler: (@Sendable (String) async throws -> CourseDetails)? { + get { getCourseDetailsState.withLock(\.handler) } + set { getCourseDetailsState.withLock { $0.handler = newValue } } + } + public func getCourseDetails(courseID: String) async throws -> CourseDetails { + let getCourseDetailsHandler = getCourseDetailsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDetailsHandler = getCourseDetailsHandler { + return try await getCourseDetailsHandler(courseID) + } + fatalError("getCourseDetailsHandler returns can't have a default value thus its handler must be set") + } + + private let getLoadedCourseDetailsState = MockoloMutex(MockoloHandlerState CourseDetails>()) + public var getLoadedCourseDetailsCallCount: Int { + return getLoadedCourseDetailsState.withLock(\.callCount) + } + public var getLoadedCourseDetailsHandler: (@Sendable (String) async throws -> CourseDetails)? { + get { getLoadedCourseDetailsState.withLock(\.handler) } + set { getLoadedCourseDetailsState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseDetails(courseID: String) async throws -> CourseDetails { + let getLoadedCourseDetailsHandler = getLoadedCourseDetailsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseDetailsHandler = getLoadedCourseDetailsHandler { + return try await getLoadedCourseDetailsHandler(courseID) + } + fatalError("getLoadedCourseDetailsHandler returns can't have a default value thus its handler must be set") + } + + private let enrollToCourseState = MockoloMutex(MockoloHandlerState Bool>()) + public var enrollToCourseCallCount: Int { + return enrollToCourseState.withLock(\.callCount) + } + public var enrollToCourseHandler: (@Sendable (String) async throws -> Bool)? { + get { enrollToCourseState.withLock(\.handler) } + set { enrollToCourseState.withLock { $0.handler = newValue } } + } + public func enrollToCourse(courseID: String) async throws -> Bool { + let enrollToCourseHandler = enrollToCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let enrollToCourseHandler = enrollToCourseHandler { + return try await enrollToCourseHandler(courseID) + } + return false + } +} + +public final class ConnectivityProtocolMock: ConnectivityProtocol, @unchecked Sendable { + public init() { } + public init(isInternetAvaliable: Bool = false, isMobileData: Bool = false) { + self.isInternetAvaliable = isInternetAvaliable + self.isMobileData = isMobileData + } + + + + public var isInternetAvaliable: Bool = false + + + public var isMobileData: Bool = false + + + private var _internetReachableSubject: CurrentValueSubject! + public var internetReachableSubject: CurrentValueSubject { + get { return _internetReachableSubject } + set { _internetReachableSubject = newValue } + } +} + +public final class DownloadManagerProtocolMock: DownloadManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCurrentDownloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var getCurrentDownloadTaskCallCount: Int { + return getCurrentDownloadTaskState.withLock(\.callCount) + } + public var getCurrentDownloadTaskHandler: (@Sendable () async -> DownloadDataTask?)? { + get { getCurrentDownloadTaskState.withLock(\.handler) } + set { getCurrentDownloadTaskState.withLock { $0.handler = newValue } } + } + public func getCurrentDownloadTask() async -> DownloadDataTask? { + let getCurrentDownloadTaskHandler = getCurrentDownloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCurrentDownloadTaskHandler = getCurrentDownloadTaskHandler { + return await getCurrentDownloadTaskHandler() + } + return nil + } + + private let eventPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var eventPublisherCallCount: Int { + return eventPublisherState.withLock(\.callCount) + } + public var eventPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { eventPublisherState.withLock(\.handler) } + set { eventPublisherState.withLock { $0.handler = newValue } } + } + public func eventPublisher() -> AnyPublisher { + let eventPublisherHandler = eventPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let eventPublisherHandler = eventPublisherHandler { + return eventPublisherHandler() + } + fatalError("eventPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([CourseBlock]) async throws -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock]) async throws { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + try await addToDownloadQueueHandler(blocks) + } + + } + + private let getDownloadTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksCallCount: Int { + return getDownloadTasksState.withLock(\.callCount) + } + public var getDownloadTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadTasksState.withLock(\.handler) } + set { getDownloadTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadTasks() async -> [DownloadDataTask] { + let getDownloadTasksHandler = getDownloadTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksHandler = getDownloadTasksHandler { + return await getDownloadTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksForCourseCallCount: Int { + return getDownloadTasksForCourseState.withLock(\.callCount) + } + public var getDownloadTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadTasksForCourseState.withLock(\.handler) } + set { getDownloadTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadTasksForCourseHandler = getDownloadTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksForCourseHandler = getDownloadTasksForCourseHandler { + return await getDownloadTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let cancelDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCallCount: Int { + return cancelDownloadingState.withLock(\.callCount) + } + public var cancelDownloadingHandler: (@Sendable (String, [CourseBlock]) async throws -> ())? { + get { cancelDownloadingState.withLock(\.handler) } + set { cancelDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String, blocks: [CourseBlock]) async throws { + let cancelDownloadingHandler = cancelDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingHandler = cancelDownloadingHandler { + try await cancelDownloadingHandler(courseId, blocks) + } + + } + + private let cancelDownloadingTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingTaskCallCount: Int { + return cancelDownloadingTaskState.withLock(\.callCount) + } + public var cancelDownloadingTaskHandler: (@Sendable (DownloadDataTask) async throws -> ())? { + get { cancelDownloadingTaskState.withLock(\.handler) } + set { cancelDownloadingTaskState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(task: DownloadDataTask) async throws { + let cancelDownloadingTaskHandler = cancelDownloadingTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingTaskHandler = cancelDownloadingTaskHandler { + try await cancelDownloadingTaskHandler(task) + } + + } + + private let cancelDownloadingCourseIdState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCourseIdCallCount: Int { + return cancelDownloadingCourseIdState.withLock(\.callCount) + } + public var cancelDownloadingCourseIdHandler: (@Sendable (String) async throws -> ())? { + get { cancelDownloadingCourseIdState.withLock(\.handler) } + set { cancelDownloadingCourseIdState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String) async throws { + let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdHandler { + try await cancelDownloadingCourseIdHandler(courseId) + } + + } + + private let cancelAllDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelAllDownloadingCallCount: Int { + return cancelAllDownloadingState.withLock(\.callCount) + } + public var cancelAllDownloadingHandler: (@Sendable () async throws -> ())? { + get { cancelAllDownloadingState.withLock(\.handler) } + set { cancelAllDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelAllDownloading() async throws { + let cancelAllDownloadingHandler = cancelAllDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelAllDownloadingHandler = cancelAllDownloadingHandler { + try await cancelAllDownloadingHandler() + } + + } + + private let deleteAllState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllCallCount: Int { + return deleteAllState.withLock(\.callCount) + } + public var deleteAllHandler: (@Sendable () async -> ())? { + get { deleteAllState.withLock(\.handler) } + set { deleteAllState.withLock { $0.handler = newValue } } + } + public func deleteAll() async { + let deleteAllHandler = deleteAllState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllHandler = deleteAllHandler { + await deleteAllHandler() + } + + } + + private let fileUrlState = MockoloMutex(MockoloHandlerState URL?>()) + public var fileUrlCallCount: Int { + return fileUrlState.withLock(\.callCount) + } + public var fileUrlHandler: (@Sendable (String) async -> URL?)? { + get { fileUrlState.withLock(\.handler) } + set { fileUrlState.withLock { $0.handler = newValue } } + } + public func fileUrl(for blockId: String) async -> URL? { + let fileUrlHandler = fileUrlState.withLock { state in + state.callCount += 1 + return state.handler + } + if let fileUrlHandler = fileUrlHandler { + return await fileUrlHandler(blockId) + } + return nil + } + + private let resumeDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var resumeDownloadingCallCount: Int { + return resumeDownloadingState.withLock(\.callCount) + } + public var resumeDownloadingHandler: (@Sendable () async throws -> ())? { + get { resumeDownloadingState.withLock(\.handler) } + set { resumeDownloadingState.withLock { $0.handler = newValue } } + } + public func resumeDownloading() async throws { + let resumeDownloadingHandler = resumeDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resumeDownloadingHandler = resumeDownloadingHandler { + try await resumeDownloadingHandler() + } + + } + + private let isLargeVideosSizeState = MockoloMutex(MockoloHandlerState Bool>()) + public var isLargeVideosSizeCallCount: Int { + return isLargeVideosSizeState.withLock(\.callCount) + } + public var isLargeVideosSizeHandler: (@Sendable ([CourseBlock]) async -> Bool)? { + get { isLargeVideosSizeState.withLock(\.handler) } + set { isLargeVideosSizeState.withLock { $0.handler = newValue } } + } + public func isLargeVideosSize(blocks: [CourseBlock]) async -> Bool { + let isLargeVideosSizeHandler = isLargeVideosSizeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isLargeVideosSizeHandler = isLargeVideosSizeHandler { + return await isLargeVideosSizeHandler(blocks) + } + return false + } + + private let removeAppSupportDirectoryUnusedContentState = MockoloMutex(MockoloHandlerState ()>()) + public var removeAppSupportDirectoryUnusedContentCallCount: Int { + return removeAppSupportDirectoryUnusedContentState.withLock(\.callCount) + } + public var removeAppSupportDirectoryUnusedContentHandler: (@Sendable () -> ())? { + get { removeAppSupportDirectoryUnusedContentState.withLock(\.handler) } + set { removeAppSupportDirectoryUnusedContentState.withLock { $0.handler = newValue } } + } + public func removeAppSupportDirectoryUnusedContent() { + let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentHandler { + removeAppSupportDirectoryUnusedContentHandler() + } + + } + + private let deleteState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteCallCount: Int { + return deleteState.withLock(\.callCount) + } + public var deleteHandler: (@Sendable ([CourseBlock], String) async -> ())? { + get { deleteState.withLock(\.handler) } + set { deleteState.withLock { $0.handler = newValue } } + } + public func delete(blocks: [CourseBlock], courseId: String) async { + let deleteHandler = deleteState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteHandler = deleteHandler { + await deleteHandler(blocks, courseId) + } + + } + + private let downloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadTaskCallCount: Int { + return downloadTaskState.withLock(\.callCount) + } + public var downloadTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadTaskState.withLock(\.handler) } + set { downloadTaskState.withLock { $0.handler = newValue } } + } + public func downloadTask(for blockId: String) async -> DownloadDataTask? { + let downloadTaskHandler = downloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadTaskHandler = downloadTaskHandler { + return await downloadTaskHandler(blockId) + } + return nil + } + + private let getFreeDiskSpaceState = MockoloMutex(MockoloHandlerState Int?>()) + public var getFreeDiskSpaceCallCount: Int { + return getFreeDiskSpaceState.withLock(\.callCount) + } + public var getFreeDiskSpaceHandler: (@Sendable () -> Int?)? { + get { getFreeDiskSpaceState.withLock(\.handler) } + set { getFreeDiskSpaceState.withLock { $0.handler = newValue } } + } + public func getFreeDiskSpace() -> Int? { + let getFreeDiskSpaceHandler = getFreeDiskSpaceState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getFreeDiskSpaceHandler = getFreeDiskSpaceHandler { + return getFreeDiskSpaceHandler() + } + return nil + } +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { + print("At \(function), the captured arguments are not Sendable, it is not concurrency-safe.") +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { +} + +/// Will be replaced to `Synchronization.Mutex` in future. +fileprivate final class MockoloMutex: @unchecked Sendable { + private let lock = NSLock() + private var value: Value + init(_ initialValue: Value) { + self.value = initialValue + } +#if compiler(>=6.0) + borrowing func withLock(_ body: (inout sending Value) throws(E) -> Result) throws(E) -> sending Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#else + func withLock(_ body: (inout Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#endif +} + +fileprivate struct MockoloUnsafeTransfer: @unchecked Sendable { + var value: Value + init(_ value: Value) { + self.value = value + } +} + +fileprivate struct MockoloHandlerState { + var argValues: [MockoloUnsafeTransfer] = [] + var handler: Handler? = nil + var callCount: Int = 0 +} + diff --git a/Discovery/DiscoveryTests/Presentation/CourseDetailsViewModelTests.swift b/Discovery/DiscoveryTests/Presentation/CourseDetailsViewModelTests.swift index f88e5914a..9116f8bcf 100644 --- a/Discovery/DiscoveryTests/Presentation/CourseDetailsViewModelTests.swift +++ b/Discovery/DiscoveryTests/Presentation/CourseDetailsViewModelTests.swift @@ -2,10 +2,9 @@ // CourseDetailsViewModelTests.swift // CourseDetailsTests // -// Created by  Stepanok Ivan on 20.01.2023. +// Created by Stepanok Ivan on 20.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Discovery @@ -22,17 +21,19 @@ final class CourseDetailsViewModelTests: XCTestCase { let config = ConfigMock() let cssInjector = CSSInjectorMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - - let viewModel = CourseDetailsViewModel(interactor: interactor, - router: router, - analytics: analytics, - config: config, - cssInjector: cssInjector, - connectivity: connectivity, - storage: CoreStorageMock()) - + + connectivity.isInternetAvaliable = true + + let viewModel = CourseDetailsViewModel( + interactor: interactor, + router: router, + analytics: analytics, + config: config, + cssInjector: cssInjector, + connectivity: connectivity, + storage: CoreStorageMock() + ) + let courseDetails = CourseDetails( courseID: "123", org: "org", @@ -48,20 +49,19 @@ final class CourseDetailsViewModelTests: XCTestCase { courseVideoURL: nil, courseRawImage: nil ) - - - Given(interactor, .getCourseDetails(courseID: "123", - willReturn: courseDetails)) - + + + interactor.getCourseDetailsHandler = { _ in courseDetails } + await viewModel.getCourseDetail(courseID: "123") - - Verify(interactor, 1, .getCourseDetails(courseID: .any)) - + + XCTAssertEqual(interactor.getCourseDetailsCallCount, 1) + XCTAssertFalse(viewModel.isShowProgress) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.showError) } - + func testGetCourseDetailSuccessOffline() async throws { let interactor = DiscoveryInteractorProtocolMock() let router = DiscoveryRouterMock() @@ -69,17 +69,19 @@ final class CourseDetailsViewModelTests: XCTestCase { let config = ConfigMock() let cssInjector = CSSInjectorMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: false)) - - let viewModel = CourseDetailsViewModel(interactor: interactor, - router: router, - analytics: analytics, - config: config, - cssInjector: cssInjector, - connectivity: connectivity, - storage: CoreStorageMock()) - + + connectivity.isInternetAvaliable = false + + let viewModel = CourseDetailsViewModel( + interactor: interactor, + router: router, + analytics: analytics, + config: config, + cssInjector: cssInjector, + connectivity: connectivity, + storage: CoreStorageMock() + ) + let courseDetails = CourseDetails( courseID: "123", org: "org", @@ -95,19 +97,18 @@ final class CourseDetailsViewModelTests: XCTestCase { courseVideoURL: nil, courseRawImage: nil ) - - Given(interactor, .getLoadedCourseDetails(courseID: "123", - willReturn: courseDetails)) - + + interactor.getLoadedCourseDetailsHandler = { _ in courseDetails } + await viewModel.getCourseDetail(courseID: "123") - - Verify(interactor, 1, .getLoadedCourseDetails(courseID: .any)) - + + XCTAssertEqual(interactor.getLoadedCourseDetailsCallCount, 1) + XCTAssertFalse(viewModel.isShowProgress) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.showError) } - + func testGetCourseDetailNoInternetError() async throws { let interactor = DiscoveryInteractorProtocolMock() let router = DiscoveryRouterMock() @@ -115,31 +116,32 @@ final class CourseDetailsViewModelTests: XCTestCase { let config = ConfigMock() let cssInjector = CSSInjectorMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - - let viewModel = CourseDetailsViewModel(interactor: interactor, - router: router, - analytics: analytics, - config: config, - cssInjector: cssInjector, - connectivity: connectivity, - storage: CoreStorageMock()) - + + connectivity.isInternetAvaliable = true + + let viewModel = CourseDetailsViewModel( + interactor: interactor, + router: router, + analytics: analytics, + config: config, + cssInjector: cssInjector, + connectivity: connectivity, + storage: CoreStorageMock() + ) + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - Given(interactor, .getCourseDetails(courseID: "123", - willThrow: noInternetError)) - + interactor.getCourseDetailsHandler = { _ in throw noInternetError } + await viewModel.getCourseDetail(courseID: "123") - - Verify(interactor, 1, .getCourseDetails(courseID: .any)) - + + XCTAssertEqual(interactor.getCourseDetailsCallCount, 1) + XCTAssertFalse(viewModel.isShowProgress) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertTrue(viewModel.showError) } - + func testGetCourseDetailNoCacheError() async throws { let interactor = DiscoveryInteractorProtocolMock() let router = DiscoveryRouterMock() @@ -147,29 +149,30 @@ final class CourseDetailsViewModelTests: XCTestCase { let config = ConfigMock() let cssInjector = CSSInjectorMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - - let viewModel = CourseDetailsViewModel(interactor: interactor, - router: router, - analytics: analytics, - config: config, - cssInjector: cssInjector, - connectivity: connectivity, - storage: CoreStorageMock()) - - Given(interactor, .getCourseDetails(courseID: "123", - willThrow: NoCachedDataError())) - + + connectivity.isInternetAvaliable = true + + let viewModel = CourseDetailsViewModel( + interactor: interactor, + router: router, + analytics: analytics, + config: config, + cssInjector: cssInjector, + connectivity: connectivity, + storage: CoreStorageMock() + ) + + interactor.getCourseDetailsHandler = { _ in throw NoCachedDataError() } + await viewModel.getCourseDetail(courseID: "123") - - Verify(interactor, 1, .getCourseDetails(courseID: .any)) - + + XCTAssertEqual(interactor.getCourseDetailsCallCount, 1) + XCTAssertFalse(viewModel.isShowProgress) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertTrue(viewModel.showError) } - + func testGetCourseDetailUnknownError() async throws { let interactor = DiscoveryInteractorProtocolMock() let router = DiscoveryRouterMock() @@ -177,29 +180,30 @@ final class CourseDetailsViewModelTests: XCTestCase { let config = ConfigMock() let cssInjector = CSSInjectorMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - - let viewModel = CourseDetailsViewModel(interactor: interactor, - router: router, - analytics: analytics, - config: config, - cssInjector: cssInjector, - connectivity: connectivity, - storage: CoreStorageMock()) - - Given(interactor, .getCourseDetails(courseID: "123", - willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + + connectivity.isInternetAvaliable = true + + let viewModel = CourseDetailsViewModel( + interactor: interactor, + router: router, + analytics: analytics, + config: config, + cssInjector: cssInjector, + connectivity: connectivity, + storage: CoreStorageMock() + ) + + interactor.getCourseDetailsHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + await viewModel.getCourseDetail(courseID: "123") - - Verify(interactor, 1, .getCourseDetails(courseID: .any)) - + + XCTAssertEqual(interactor.getCourseDetailsCallCount, 1) + XCTAssertFalse(viewModel.isShowProgress) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertTrue(viewModel.showError) } - + func testEnrollToCourseSuccess() async throws { let interactor = DiscoveryInteractorProtocolMock() let router = DiscoveryRouterMock() @@ -207,30 +211,32 @@ final class CourseDetailsViewModelTests: XCTestCase { let config = ConfigMock() let cssInjector = CSSInjectorMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - - let viewModel = CourseDetailsViewModel(interactor: interactor, - router: router, - analytics: analytics, - config: config, - cssInjector: cssInjector, - connectivity: connectivity, - storage: CoreStorageMock()) - - Given(interactor, .enrollToCourse(courseID: "123", willReturn: true)) - + + connectivity.isInternetAvaliable = true + + let viewModel = CourseDetailsViewModel( + interactor: interactor, + router: router, + analytics: analytics, + config: config, + cssInjector: cssInjector, + connectivity: connectivity, + storage: CoreStorageMock() + ) + + interactor.enrollToCourseHandler = { _ in true } + await viewModel.enrollToCourse(id: "123") - - Verify(interactor, 1, .enrollToCourse(courseID: .any)) - Verify(analytics, .courseEnrollClicked(courseId: .any, courseName: .any)) - Verify(analytics, .courseEnrollSuccess(courseId: .any, courseName: .any)) - + + XCTAssertEqual(interactor.enrollToCourseCallCount, 1) + XCTAssertTrue(analytics.courseEnrollClickedCallCount > 0) + XCTAssertTrue(analytics.courseEnrollSuccessCallCount > 0) + XCTAssertFalse(viewModel.isShowProgress) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.showError) } - + func testEnrollToCourseUnknownError() async throws { let interactor = DiscoveryInteractorProtocolMock() let router = DiscoveryRouterMock() @@ -238,30 +244,31 @@ final class CourseDetailsViewModelTests: XCTestCase { let config = ConfigMock() let cssInjector = CSSInjectorMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - - let viewModel = CourseDetailsViewModel(interactor: interactor, - router: router, - analytics: analytics, - config: config, - cssInjector: cssInjector, - connectivity: connectivity, - storage: CoreStorageMock()) - - Given(interactor, .enrollToCourse(courseID: "123", - willThrow: AFError.explicitlyCancelled)) - + + connectivity.isInternetAvaliable = true + + let viewModel = CourseDetailsViewModel( + interactor: interactor, + router: router, + analytics: analytics, + config: config, + cssInjector: cssInjector, + connectivity: connectivity, + storage: CoreStorageMock() + ) + + interactor.enrollToCourseHandler = { _ in throw AFError.explicitlyCancelled } + await viewModel.enrollToCourse(id: "123") - - Verify(interactor, 1, .enrollToCourse(courseID: .any)) - Verify(analytics, .courseEnrollClicked(courseId: .any, courseName: .any)) - + + XCTAssertEqual(interactor.enrollToCourseCallCount, 1) + XCTAssertTrue(analytics.courseEnrollClickedCallCount > 0) + XCTAssertFalse(viewModel.isShowProgress) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertTrue(viewModel.showError) } - + func testEnrollToCourseNoInternetError() async throws { let interactor = DiscoveryInteractorProtocolMock() let router = DiscoveryRouterMock() @@ -269,31 +276,32 @@ final class CourseDetailsViewModelTests: XCTestCase { let config = ConfigMock() let cssInjector = CSSInjectorMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - - let viewModel = CourseDetailsViewModel(interactor: interactor, - router: router, - analytics: analytics, - config: config, - cssInjector: cssInjector, - connectivity: connectivity, - storage: CoreStorageMock()) - + + connectivity.isInternetAvaliable = true + + let viewModel = CourseDetailsViewModel( + interactor: interactor, + router: router, + analytics: analytics, + config: config, + cssInjector: cssInjector, + connectivity: connectivity, + storage: CoreStorageMock() + ) + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - Given(interactor, .enrollToCourse(courseID: "123", - willThrow: noInternetError)) - + interactor.enrollToCourseHandler = { _ in throw noInternetError } + await viewModel.enrollToCourse(id: "123") - - Verify(interactor, 1, .enrollToCourse(courseID: .any)) - + + XCTAssertEqual(interactor.enrollToCourseCallCount, 1) + XCTAssertFalse(viewModel.isShowProgress) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertTrue(viewModel.showError) } - + func testEnrollToCourseNoCacheError() async throws { let interactor = DiscoveryInteractorProtocolMock() let router = DiscoveryRouterMock() @@ -301,27 +309,28 @@ final class CourseDetailsViewModelTests: XCTestCase { let config = ConfigMock() let cssInjector = CSSInjectorMock() let connectivity = ConnectivityProtocolMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - - let viewModel = CourseDetailsViewModel(interactor: interactor, - router: router, - analytics: analytics, - config: config, - cssInjector: cssInjector, - connectivity: connectivity, - storage: CoreStorageMock()) - - Given(interactor, .enrollToCourse(courseID: "123", - willThrow: NoCachedDataError())) - + + connectivity.isInternetAvaliable = true + + let viewModel = CourseDetailsViewModel( + interactor: interactor, + router: router, + analytics: analytics, + config: config, + cssInjector: cssInjector, + connectivity: connectivity, + storage: CoreStorageMock() + ) + + interactor.enrollToCourseHandler = { _ in throw NoCachedDataError() } + await viewModel.enrollToCourse(id: "123") - - Verify(interactor, 1, .enrollToCourse(courseID: .any)) - + + XCTAssertEqual(interactor.enrollToCourseCallCount, 1) + XCTAssertFalse(viewModel.isShowProgress) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertTrue(viewModel.showError) } - + } diff --git a/Discovery/DiscoveryTests/Presentation/DiscoveryViewModelTests.swift b/Discovery/DiscoveryTests/Presentation/DiscoveryViewModelTests.swift index 8b9beb780..c51bafeff 100644 --- a/Discovery/DiscoveryTests/Presentation/DiscoveryViewModelTests.swift +++ b/Discovery/DiscoveryTests/Presentation/DiscoveryViewModelTests.swift @@ -2,10 +2,9 @@ // DiscoveryUnitTests.swift // DiscoveryUnitTests // -// Created by  Stepanok Ivan on 17.01.2023. +// Created by Stepanok Ivan on 17.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Discovery @@ -22,17 +21,19 @@ final class DiscoveryViewModelTests: XCTestCase { override func tearDownWithError() throws { // Put teardown code here. This method is called after the invocation of each test method in the class. } - + func testGetDiscoveryCourses() async throws { let interactor = DiscoveryInteractorProtocolMock() let connectivity = Connectivity(config: ConfigMock()) let analytics = DiscoveryAnalyticsMock() - let viewModel = DiscoveryViewModel(router: DiscoveryRouterMock(), - config: ConfigMock(), - interactor: interactor, - connectivity: connectivity, - analytics: analytics, - storage: CoreStorageMock()) + let viewModel = DiscoveryViewModel( + router: DiscoveryRouterMock(), + config: ConfigMock(), + interactor: interactor, + connectivity: connectivity, + analytics: analytics, + storage: CoreStorageMock() + ) let items = [ CourseItem(name: "Test", @@ -69,26 +70,28 @@ final class DiscoveryViewModelTests: XCTestCase { viewModel.courses = items + items + items viewModel.totalPages = 2 - Given(interactor, .discovery(page: 1, willReturn: items)) + interactor.discoveryHandler = { _ in items } await viewModel.getDiscoveryCourses(index: 3) - Verify(interactor, 1, .discovery(page: 1)) + XCTAssertEqual(interactor.discoveryCallCount, 1) XCTAssertFalse(viewModel.showError) XCTAssertEqual(viewModel.totalPages, 2) } - + func testDiscoverySuccess() async throws { let interactor = DiscoveryInteractorProtocolMock() let connectivity = Connectivity(config: ConfigMock()) let analytics = DiscoveryAnalyticsMock() - let viewModel = DiscoveryViewModel(router: DiscoveryRouterMock(), - config: ConfigMock(), - interactor: interactor, - connectivity: connectivity, - analytics: analytics, - storage: CoreStorageMock()) + let viewModel = DiscoveryViewModel( + router: DiscoveryRouterMock(), + config: ConfigMock(), + interactor: interactor, + connectivity: connectivity, + analytics: analytics, + storage: CoreStorageMock() + ) let items = [ CourseItem(name: "Test", org: "org", @@ -122,27 +125,29 @@ final class DiscoveryViewModelTests: XCTestCase { progressPossible: 0) ] - Given(interactor, .discovery(page: 1, willReturn: items)) + interactor.discoveryHandler = { _ in items } await viewModel.discovery(page: 1) - Verify(interactor, 1, .discovery(page: 1)) + XCTAssertEqual(interactor.discoveryCallCount, 1) XCTAssertFalse(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) XCTAssertEqual(viewModel.nextPage, 2) } - + func testDiscoveryOfflineSuccess() async throws { let interactor = DiscoveryInteractorProtocolMock() let connectivity = ConnectivityProtocolMock() let analytics = DiscoveryAnalyticsMock() - let viewModel = DiscoveryViewModel(router: DiscoveryRouterMock(), - config: ConfigMock(), - interactor: interactor, - connectivity: connectivity, - analytics: analytics, - storage: CoreStorageMock()) + let viewModel = DiscoveryViewModel( + router: DiscoveryRouterMock(), + config: ConfigMock(), + interactor: interactor, + connectivity: connectivity, + analytics: analytics, + storage: CoreStorageMock() + ) let items = [ CourseItem(name: "Test", org: "org", @@ -175,66 +180,70 @@ final class DiscoveryViewModelTests: XCTestCase { progressEarned: 0, progressPossible: 0) ] - - Given(connectivity, .isInternetAvaliable(getter: false)) - - Given(interactor, .discoveryOffline(willReturn: items)) - + + connectivity.isInternetAvaliable = false + + interactor.discoveryOfflineHandler = { items } + await viewModel.discovery(page: 1) - - Verify(interactor, 1, .discoveryOffline()) - + + XCTAssertEqual(interactor.discoveryOfflineCallCount, 1) + XCTAssertFalse(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) XCTAssertEqual(viewModel.nextPage, 2) } - + func testDiscoveryNoInternetError() async throws { let interactor = DiscoveryInteractorProtocolMock() let connectivity = Connectivity(config: ConfigMock()) let analytics = DiscoveryAnalyticsMock() - let viewModel = DiscoveryViewModel(router: DiscoveryRouterMock(), - config: ConfigMock(), - interactor: interactor, - connectivity: connectivity, - analytics: analytics, - storage: CoreStorageMock()) - + let viewModel = DiscoveryViewModel( + router: DiscoveryRouterMock(), + config: ConfigMock(), + interactor: interactor, + connectivity: connectivity, + analytics: analytics, + storage: CoreStorageMock() + ) + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .discovery(page: 1, willThrow: noInternetError)) - + + interactor.discoveryHandler = { _ in throw noInternetError } + await viewModel.discovery(page: 1) - - Verify(interactor, 1, .discovery(page: 1)) - + + XCTAssertEqual(interactor.discoveryCallCount, 1) + XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertTrue(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) } - + func testDiscoveryUnknownError() async throws { let interactor = DiscoveryInteractorProtocolMock() let connectivity = Connectivity(config: ConfigMock()) let analytics = DiscoveryAnalyticsMock() - let viewModel = DiscoveryViewModel(router: DiscoveryRouterMock(), - config: ConfigMock(), - interactor: interactor, - connectivity: connectivity, - analytics: analytics, - storage: CoreStorageMock()) - + let viewModel = DiscoveryViewModel( + router: DiscoveryRouterMock(), + config: ConfigMock(), + interactor: interactor, + connectivity: connectivity, + analytics: analytics, + storage: CoreStorageMock() + ) + let noInternetError = AFError.sessionInvalidated(error: NSError()) - - Given(interactor, .discovery(page: 1, willThrow: noInternetError)) - + + interactor.discoveryHandler = { _ in throw noInternetError } + await viewModel.discovery(page: 1) - - Verify(interactor, 1, .discovery(page: 1)) - + + XCTAssertEqual(interactor.discoveryCallCount, 1) + XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertTrue(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) } - + } diff --git a/Discovery/DiscoveryTests/Presentation/SearchViewModelTests.swift b/Discovery/DiscoveryTests/Presentation/SearchViewModelTests.swift index d837f982c..f8d805f3c 100644 --- a/Discovery/DiscoveryTests/Presentation/SearchViewModelTests.swift +++ b/Discovery/DiscoveryTests/Presentation/SearchViewModelTests.swift @@ -5,7 +5,6 @@ // Created by Paul Maul on 14.02.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Discovery @@ -22,7 +21,7 @@ final class SearchViewModelTests: XCTestCase { override func tearDownWithError() throws { // Put teardown code here. This method is called after the invocation of each test method in the class. } - + func testSearchSuccess() async throws { let interactor = DiscoveryInteractorProtocolMock() let connectivity = Connectivity(config: ConfigMock()) @@ -32,11 +31,11 @@ final class SearchViewModelTests: XCTestCase { interactor: interactor, connectivity: connectivity, router: router, - analytics: analytics, + analytics: analytics, storage: CoreStorageMock(), debounce: .test ) - + let items = [ CourseItem(name: "Test", org: "org", @@ -70,21 +69,21 @@ final class SearchViewModelTests: XCTestCase { progressPossible: 0) ] - Given(interactor, .search(page: 1, searchTerm: .any, willReturn: items)) + interactor.searchHandler = { _, _ in items } viewModel.searchText = "Test" - + // Wait for debounce + next event loop iteration try await Task.sleep(nanoseconds: UInt64(0.5 * Double(NSEC_PER_SEC))) await Task.yield() - - Verify(interactor, .search(page: 1, searchTerm: .any)) - Verify(analytics, .discoveryCoursesSearch(label: .any, coursesCount: .any)) + + XCTAssertTrue(interactor.searchCallCount > 0) + XCTAssertTrue(analytics.discoveryCoursesSearchCallCount > 0) XCTAssertFalse(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) } - + func testSearchEmptyQuerySuccess() async throws { let interactor = DiscoveryInteractorProtocolMock() let connectivity = Connectivity(config: ConfigMock()) @@ -102,13 +101,13 @@ final class SearchViewModelTests: XCTestCase { viewModel.searchText = "" await Task.yield() - - Verify(interactor, 0, .search(page: 1, searchTerm: .any)) + + XCTAssertEqual(interactor.searchCallCount, 0) XCTAssertFalse(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) } - + func testSearchNoInternetError() async throws { let interactor = DiscoveryInteractorProtocolMock() let connectivity = Connectivity(config: ConfigMock()) @@ -125,16 +124,16 @@ final class SearchViewModelTests: XCTestCase { let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - Given(interactor, .search(page: .any, searchTerm: .any, willThrow: noInternetError)) - + interactor.searchHandler = { _, _ in throw noInternetError } + viewModel.searchText = "Test" // Wait for debounce + next event loop iteration try await Task.sleep(nanoseconds: UInt64(0.5 * Double(NSEC_PER_SEC))) await Task.yield() - - - Verify(interactor, 1, .search(page: 1, searchTerm: .any)) + + + XCTAssertEqual(interactor.searchCallCount, 1) XCTAssertTrue(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) @@ -156,16 +155,16 @@ final class SearchViewModelTests: XCTestCase { ) let unknownError = AFError.sessionInvalidated(error: NSError()) - - Given(interactor, .search(page: .any, searchTerm: .any, willThrow: unknownError)) + + interactor.searchHandler = { _, _ in throw unknownError } viewModel.searchText = "Test" - + // Wait for debounce + next event loop iteration try await Task.sleep(nanoseconds: UInt64(0.5 * Double(NSEC_PER_SEC))) await Task.yield() - Verify(interactor, 1, .search(page: 1, searchTerm: .any)) + XCTAssertEqual(interactor.searchCallCount, 1) XCTAssertTrue(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) diff --git a/Discovery/Mockfile b/Discovery/Mockfile deleted file mode 100644 index dcd8b112b..000000000 --- a/Discovery/Mockfile +++ /dev/null @@ -1,18 +0,0 @@ -sourceryCommand: mint run krzysztofzablocki/Sourcery@2.1.2 sourcery -sourceryTemplate: ../MockTemplate.swifttemplate -unit.tests.mock: - sources: - include: - - ./../Core - - ./Discovery - exclude: [] - output: ./DiscoveryTests/DiscoveryMock.generated.swift - targets: - - MyAppUnitTests - import: - - Core - - Discovery - - Foundation - - SwiftUI - - Combine - - OEXFoundation \ No newline at end of file diff --git a/Discussion/Discussion.xcodeproj/project.pbxproj b/Discussion/Discussion.xcodeproj/project.pbxproj index d77f1bcb9..a56151468 100644 --- a/Discussion/Discussion.xcodeproj/project.pbxproj +++ b/Discussion/Discussion.xcodeproj/project.pbxproj @@ -23,7 +23,6 @@ 023F14AB291BF30300FD0EFF /* CommentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023F14AA291BF30300FD0EFF /* CommentCell.swift */; }; 0240D8D22987FE1F003CFE50 /* PostViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0240D8D12987FE1F003CFE50 /* PostViewModelTests.swift */; }; 0240D8D32987FE1F003CFE50 /* Discussion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0218194D28F7344A00202564 /* Discussion.framework */; platformFilter = ios; }; - 0240D8DE2987FF91003CFE50 /* DiscussionMock.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0240D8DD2987FF91003CFE50 /* DiscussionMock.generated.swift */; }; 02426DE42983DD4D00B31E6C /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 02426DE62983DD4D00B31E6C /* Localizable.stringsdict */; }; 027BD39A2908256200392132 /* ThreadList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 027BD3992908256200392132 /* ThreadList.swift */; }; 0282DA5F28F893CA003C3F07 /* PostsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0282DA5E28F893CA003C3F07 /* PostsView.swift */; }; @@ -58,6 +57,7 @@ 0766DFCA299AA3D400EBEF6A /* Data_CreatedComment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0766DFC9299AA3D400EBEF6A /* Data_CreatedComment.swift */; }; 7527943BE0D66C33B167A41A /* Pods_App_Discussion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66A7A0375EDDEB8948165EAD /* Pods_App_Discussion.framework */; }; 9FC0EF907C0334E383C300C4 /* Pods_App_Discussion_DiscussionTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C40A586C6164140DC2079231 /* Pods_App_Discussion_DiscussionTests.framework */; }; + A5B4681D2F2A0EFD002A4ECA /* DiscussionMocks.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B4681B2F2A0EFD002A4ECA /* DiscussionMocks.generated.swift */; }; BA3C45672BA9E13000672C96 /* Data_DiscussionInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA3C45662BA9E13000672C96 /* Data_DiscussionInfo.swift */; }; BA3C45692BA9E18D00672C96 /* DiscussionInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA3C45682BA9E18D00672C96 /* DiscussionInfo.swift */; }; CE2691DD2D9D2868002B8B50 /* HTMLContentFixProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2691DC2D9D2868002B8B50 /* HTMLContentFixProcessor.swift */; }; @@ -124,7 +124,6 @@ 023F14AA291BF30300FD0EFF /* CommentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentCell.swift; sourceTree = ""; }; 0240D8CF2987FE1F003CFE50 /* DiscussionTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DiscussionTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 0240D8D12987FE1F003CFE50 /* PostViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewModelTests.swift; sourceTree = ""; }; - 0240D8DD2987FF91003CFE50 /* DiscussionMock.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiscussionMock.generated.swift; sourceTree = ""; }; 02426DE52983DD4D00B31E6C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; 027BD3992908256200392132 /* ThreadList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadList.swift; sourceTree = ""; }; 0282DA5E28F893CA003C3F07 /* PostsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostsView.swift; sourceTree = ""; }; @@ -167,6 +166,7 @@ 5F59EC4433FF0AE0743D284D /* Pods-App-Discussion.releaseprod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Discussion.releaseprod.xcconfig"; path = "Target Support Files/Pods-App-Discussion/Pods-App-Discussion.releaseprod.xcconfig"; sourceTree = ""; }; 66A7A0375EDDEB8948165EAD /* Pods_App_Discussion.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App_Discussion.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A55CEBCC51BDC30B8354E258 /* Pods-App-Discussion.debugprod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Discussion.debugprod.xcconfig"; path = "Target Support Files/Pods-App-Discussion/Pods-App-Discussion.debugprod.xcconfig"; sourceTree = ""; }; + A5B4681B2F2A0EFD002A4ECA /* DiscussionMocks.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscussionMocks.generated.swift; sourceTree = ""; }; ACA8EF2DEDDB7695162C381A /* Pods-App-Discussion.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Discussion.debug.xcconfig"; path = "Target Support Files/Pods-App-Discussion/Pods-App-Discussion.debug.xcconfig"; sourceTree = ""; }; ACDA8EE733B97BCD8689A0B4 /* Pods-App-Discussion.debugstage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Discussion.debugstage.xcconfig"; path = "Target Support Files/Pods-App-Discussion/Pods-App-Discussion.debugstage.xcconfig"; sourceTree = ""; }; B472516A5A79E87C40766D93 /* Pods-App-Discussion-DiscussionTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Discussion-DiscussionTests.debug.xcconfig"; path = "Target Support Files/Pods-App-Discussion-DiscussionTests/Pods-App-Discussion-DiscussionTests.debug.xcconfig"; sourceTree = ""; }; @@ -321,8 +321,8 @@ 0240D8D02987FE1F003CFE50 /* DiscussionTests */ = { isa = PBXGroup; children = ( + A5B4681C2F2A0EFD002A4ECA /* Generated */, 0766DFD8299ADAB500EBEF6A /* Presentation */, - 0240D8DD2987FF91003CFE50 /* DiscussionMock.generated.swift */, ); path = DiscussionTests; sourceTree = ""; @@ -483,6 +483,14 @@ path = Base; sourceTree = ""; }; + A5B4681C2F2A0EFD002A4ECA /* Generated */ = { + isa = PBXGroup; + children = ( + A5B4681B2F2A0EFD002A4ECA /* DiscussionMocks.generated.swift */, + ); + path = Generated; + sourceTree = ""; + }; CE517F412D9C0A9D0012EF71 /* HTMLStreamer */ = { isa = PBXGroup; children = ( @@ -566,7 +574,6 @@ 0240D8CB2987FE1F003CFE50 /* Sources */, 0240D8CC2987FE1F003CFE50 /* Frameworks */, 0240D8CD2987FE1F003CFE50 /* Resources */, - 3607DC97DFD36C230ED0AB74 /* [CP] Copy Pods Resources */, CE7CAF492CC1566D00E0AC9D /* Embed Frameworks */, ); buildRules = ( @@ -660,23 +667,6 @@ shellPath = /bin/sh; shellScript = "if [[ -f \"${PODS_ROOT}/SwiftGen/bin/swiftgen\" ]]; then\n \"${PODS_ROOT}/SwiftGen/bin/swiftgen\"\nelse\n echo \"warning: SwiftGen is not installed. Run 'pod install --repo-update' to install it.\"\nfi\n"; }; - 3607DC97DFD36C230ED0AB74 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Discussion-DiscussionTests/Pods-App-Discussion-DiscussionTests-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Discussion-DiscussionTests/Pods-App-Discussion-DiscussionTests-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App-Discussion-DiscussionTests/Pods-App-Discussion-DiscussionTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; D42AB95EE00BC248888BC25A /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -783,8 +773,8 @@ files = ( 02E4F18129A8C2FD00F31684 /* DiscussionSearchTopicsViewModelTests.swift in Sources */, 02BE57BC29890D4A00197812 /* DiscussionTopicsViewModelTests.swift in Sources */, + A5B4681D2F2A0EFD002A4ECA /* DiscussionMocks.generated.swift in Sources */, 020767682989528B00B976DE /* CreateNewThreadViewModelTests.swift in Sources */, - 0240D8DE2987FF91003CFE50 /* DiscussionMock.generated.swift in Sources */, 02BE57BE298910BD00197812 /* BaseResponsesViewModelTests.swift in Sources */, 020767662989393200B976DE /* ResponsesViewModelTests.swift in Sources */, 0201771C29883E96003AC5EF /* ThreadViewModelTests.swift in Sources */, diff --git a/Discussion/Discussion/Domain/DiscussionInteractor.swift b/Discussion/Discussion/Domain/DiscussionInteractor.swift index b515f7c88..6c8a03db8 100644 --- a/Discussion/Discussion/Domain/DiscussionInteractor.swift +++ b/Discussion/Discussion/Domain/DiscussionInteractor.swift @@ -8,7 +8,7 @@ import Foundation import Core -//sourcery: AutoMockable +/// @mockable public protocol DiscussionInteractorProtocol: Sendable { func getCourseDiscussionInfo(courseID: String) async throws -> DiscussionInfo func getThreadsList(courseID: String, diff --git a/Discussion/Discussion/Presentation/Comments/Responses/ResponsesView.swift b/Discussion/Discussion/Presentation/Comments/Responses/ResponsesView.swift index 0b943be91..7f56caeeb 100644 --- a/Discussion/Discussion/Presentation/Comments/Responses/ResponsesView.swift +++ b/Discussion/Discussion/Presentation/Comments/Responses/ResponsesView.swift @@ -258,11 +258,11 @@ struct ResponsesView_Previews: PreviewProvider { let viewModel = ResponsesViewModel( courseID: "", interactor: DiscussionInteractor(repository: DiscussionRepositoryMock()), - router: DiscussionRouterMock(), + router: DiscussionRouterPreviewMock(), config: ConfigMock(), storage: CoreStorageMock(), threadStateSubject: .init(nil), - analytics: DiscussionAnalyticsMock() + analytics: DiscussionAnalyticsPreviewMock() ) let post = Post( authorName: "Kirill", @@ -283,8 +283,8 @@ struct ResponsesView_Previews: PreviewProvider { abuseFlagged: false, closed: false ) - let router = DiscussionRouterMock() - + let router = DiscussionRouterPreviewMock() + ResponsesView( commentID: "", viewModel: viewModel, diff --git a/Discussion/Discussion/Presentation/Comments/Thread/ThreadView.swift b/Discussion/Discussion/Presentation/Comments/Thread/ThreadView.swift index b673630bc..96c27e049 100644 --- a/Discussion/Discussion/Presentation/Comments/Thread/ThreadView.swift +++ b/Discussion/Discussion/Presentation/Comments/Thread/ThreadView.swift @@ -303,11 +303,11 @@ struct CommentsView_Previews: PreviewProvider { numPages: 3) let vm = ThreadViewModel( interactor: DiscussionInteractor.mock, - router: DiscussionRouterMock(), + router: DiscussionRouterPreviewMock(), config: ConfigMock(), storage: CoreStorageMock(), postStateSubject: .init(nil), - analytics: DiscussionAnalyticsMock() + analytics: DiscussionAnalyticsPreviewMock() ) ThreadView(thread: userThread, viewModel: vm) diff --git a/Discussion/Discussion/Presentation/CreateNewThread/CreateNewThreadView.swift b/Discussion/Discussion/Presentation/CreateNewThread/CreateNewThreadView.swift index e630c9b8d..182e34945 100644 --- a/Discussion/Discussion/Presentation/CreateNewThread/CreateNewThreadView.swift +++ b/Discussion/Discussion/Presentation/CreateNewThread/CreateNewThreadView.swift @@ -215,9 +215,9 @@ struct AddTopic_Previews: PreviewProvider { static var previews: some View { let vm = CreateNewThreadViewModel( interactor: DiscussionInteractor.mock, - router: DiscussionRouterMock(), + router: DiscussionRouterPreviewMock(), config: ConfigMock(), - analytics: DiscussionAnalyticsMock(), + analytics: DiscussionAnalyticsPreviewMock(), storage: CoreStorageMock() ) diff --git a/Discussion/Discussion/Presentation/DiscussionAnalytics.swift b/Discussion/Discussion/Presentation/DiscussionAnalytics.swift index 5768c0568..3ad0112dd 100644 --- a/Discussion/Discussion/Presentation/DiscussionAnalytics.swift +++ b/Discussion/Discussion/Presentation/DiscussionAnalytics.swift @@ -7,7 +7,7 @@ import Foundation -//sourcery: AutoMockable +/// @mockable public protocol DiscussionAnalytics { func discussionAllPostsClicked(courseId: String, courseName: String) func discussionFollowingClicked(courseId: String, courseName: String) @@ -66,7 +66,7 @@ public protocol DiscussionAnalytics { } #if DEBUG -class DiscussionAnalyticsMock: DiscussionAnalytics { +class DiscussionAnalyticsPreviewMock: DiscussionAnalytics { public func discussionAllPostsClicked(courseId: String, courseName: String) {} public func discussionFollowingClicked(courseId: String, courseName: String) {} public func discussionTopicClicked(courseId: String, courseName: String, topicId: String, topicName: String) {} diff --git a/Discussion/Discussion/Presentation/DiscussionRouter.swift b/Discussion/Discussion/Presentation/DiscussionRouter.swift index e2a1b3e9d..ca48e87c4 100644 --- a/Discussion/Discussion/Presentation/DiscussionRouter.swift +++ b/Discussion/Discussion/Presentation/DiscussionRouter.swift @@ -9,7 +9,7 @@ import Foundation import Core import Combine -//sourcery: AutoMockable +/// @mockable @MainActor public protocol DiscussionRouter: BaseRouter { @@ -47,12 +47,12 @@ public protocol DiscussionRouter: BaseRouter { // Mark - For testing and SwiftUI preview #if DEBUG -public class DiscussionRouterMock: BaseRouterMock, DiscussionRouter { - +public class DiscussionRouterPreviewMock: BaseRouterMock, DiscussionRouter { + public override init() {} - + public func showUserDetails(username: String) {} - + public func showThreads( courseID: String, topics: Topics, @@ -61,7 +61,7 @@ public class DiscussionRouterMock: BaseRouterMock, DiscussionRouter { isBlackedOut: Bool, animated: Bool ) {} - + public func showThread( thread: UserThread, postStateSubject: CurrentValueSubject, @@ -70,7 +70,7 @@ public class DiscussionRouterMock: BaseRouterMock, DiscussionRouter { ) {} public func showDiscussionsSearch(courseID: String, isBlackedOut: Bool) {} - + public func showComments( courseID: String, commentID: String, diff --git a/Discussion/Discussion/Presentation/DiscussionTopics/DiscussionSearchTopicsView.swift b/Discussion/Discussion/Presentation/DiscussionTopics/DiscussionSearchTopicsView.swift index aedba367d..622bc60b3 100644 --- a/Discussion/Discussion/Presentation/DiscussionTopics/DiscussionSearchTopicsView.swift +++ b/Discussion/Discussion/Presentation/DiscussionTopics/DiscussionSearchTopicsView.swift @@ -198,7 +198,7 @@ struct DiscussionSearchTopicsView_Previews: PreviewProvider { courseID: "123", interactor: DiscussionInteractor.mock, storage: CoreStorageMock(), - router: DiscussionRouterMock(), + router: DiscussionRouterPreviewMock(), debounce: .searchDebounce ) diff --git a/Discussion/Discussion/Presentation/DiscussionTopics/DiscussionTopicsView.swift b/Discussion/Discussion/Presentation/DiscussionTopics/DiscussionTopicsView.swift index 61106f87a..20a637c6c 100644 --- a/Discussion/Discussion/Presentation/DiscussionTopics/DiscussionTopicsView.swift +++ b/Discussion/Discussion/Presentation/DiscussionTopics/DiscussionTopicsView.swift @@ -232,11 +232,11 @@ struct DiscussionView_Previews: PreviewProvider { let vm = DiscussionTopicsViewModel( title: "Course name", interactor: DiscussionInteractor.mock, - router: DiscussionRouterMock(), - analytics: DiscussionAnalyticsMock(), + router: DiscussionRouterPreviewMock(), + analytics: DiscussionAnalyticsPreviewMock(), config: ConfigMock() ) - let router = DiscussionRouterMock() + let router = DiscussionRouterPreviewMock() DiscussionTopicsView( courseID: "", diff --git a/Discussion/Discussion/Presentation/Posts/PostsView.swift b/Discussion/Discussion/Presentation/Posts/PostsView.swift index f3bfd7dc1..3985d59b8 100644 --- a/Discussion/Discussion/Presentation/Posts/PostsView.swift +++ b/Discussion/Discussion/Presentation/Posts/PostsView.swift @@ -325,7 +325,7 @@ public struct PostsView: View { struct PostsView_Previews: PreviewProvider { static var previews: some View { let topics = Topics(coursewareTopics: [], nonCoursewareTopics: []) - let router = DiscussionRouterMock() + let router = DiscussionRouterPreviewMock() let vm = PostsViewModel( interactor: DiscussionInteractor.mock, router: router, diff --git a/Discussion/DiscussionTests/DiscussionMock.generated.swift b/Discussion/DiscussionTests/DiscussionMock.generated.swift deleted file mode 100644 index 78a221249..000000000 --- a/Discussion/DiscussionTests/DiscussionMock.generated.swift +++ /dev/null @@ -1,6386 +0,0 @@ -// Generated using Sourcery 2.1.2 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT - - -// Generated with SwiftyMocky 4.2.0 -// Required Sourcery: 1.8.0 - - -import SwiftyMocky -import XCTest -import Core -import Discussion -import Foundation -import SwiftUI -import Combine -import OEXFoundation - - -// MARK: - AuthInteractorProtocol - -open class AuthInteractorProtocolMock: AuthInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - @discardableResult - open func login(username: String, password: String) throws -> User { - addInvocation(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) - let perform = methodPerformValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) as? (String, String) -> Void - perform?(`username`, `password`) - var __value: User - do { - __value = try methodReturnValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(username: String, password: String). Use given") - Failure("Stub return value not specified for login(username: String, password: String). Use given") - } catch { - throw error - } - return __value - } - - @discardableResult - open func login(externalToken: String, backend: String) throws -> User { - addInvocation(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) - let perform = methodPerformValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) as? (String, String) -> Void - perform?(`externalToken`, `backend`) - var __value: User - do { - __value = try methodReturnValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - Failure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - } catch { - throw error - } - return __value - } - - open func login(ssoToken: String) throws -> User { - addInvocation(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) - let perform = methodPerformValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) as? (String) -> Void - perform?(`ssoToken`) - var __value: User - do { - __value = try methodReturnValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(ssoToken: String). Use given") - Failure("Stub return value not specified for login(ssoToken: String). Use given") - } catch { - throw error - } - return __value - } - - open func resetPassword(email: String) throws -> ResetPassword { - addInvocation(.m_resetPassword__email_email(Parameter.value(`email`))) - let perform = methodPerformValue(.m_resetPassword__email_email(Parameter.value(`email`))) as? (String) -> Void - perform?(`email`) - var __value: ResetPassword - do { - __value = try methodReturnValue(.m_resetPassword__email_email(Parameter.value(`email`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for resetPassword(email: String). Use given") - Failure("Stub return value not specified for resetPassword(email: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCookies(force: Bool) throws { - addInvocation(.m_getCookies__force_force(Parameter.value(`force`))) - let perform = methodPerformValue(.m_getCookies__force_force(Parameter.value(`force`))) as? (Bool) -> Void - perform?(`force`) - do { - _ = try methodReturnValue(.m_getCookies__force_force(Parameter.value(`force`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getRegistrationFields() throws -> [PickerFields] { - addInvocation(.m_getRegistrationFields) - let perform = methodPerformValue(.m_getRegistrationFields) as? () -> Void - perform?() - var __value: [PickerFields] - do { - __value = try methodReturnValue(.m_getRegistrationFields).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getRegistrationFields(). Use given") - Failure("Stub return value not specified for getRegistrationFields(). Use given") - } catch { - throw error - } - return __value - } - - open func registerUser(fields: [String: String], isSocial: Bool) throws -> User { - addInvocation(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) - let perform = methodPerformValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) as? ([String: String], Bool) -> Void - perform?(`fields`, `isSocial`) - var __value: User - do { - __value = try methodReturnValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - Failure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - } catch { - throw error - } - return __value - } - - open func validateRegistrationFields(fields: [String: String]) throws -> [String: String] { - addInvocation(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) - let perform = methodPerformValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) as? ([String: String]) -> Void - perform?(`fields`) - var __value: [String: String] - do { - __value = try methodReturnValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - Failure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_login__username_usernamepassword_password(Parameter, Parameter) - case m_login__externalToken_externalTokenbackend_backend(Parameter, Parameter) - case m_login__ssoToken_ssoToken(Parameter) - case m_resetPassword__email_email(Parameter) - case m_getCookies__force_force(Parameter) - case m_getRegistrationFields - case m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>, Parameter) - case m_validateRegistrationFields__fields_fields(Parameter<[String: String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_login__username_usernamepassword_password(let lhsUsername, let lhsPassword), .m_login__username_usernamepassword_password(let rhsUsername, let rhsPassword)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsername, rhs: rhsUsername, with: matcher), lhsUsername, rhsUsername, "username")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPassword, rhs: rhsPassword, with: matcher), lhsPassword, rhsPassword, "password")) - return Matcher.ComparisonResult(results) - - case (.m_login__externalToken_externalTokenbackend_backend(let lhsExternaltoken, let lhsBackend), .m_login__externalToken_externalTokenbackend_backend(let rhsExternaltoken, let rhsBackend)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsExternaltoken, rhs: rhsExternaltoken, with: matcher), lhsExternaltoken, rhsExternaltoken, "externalToken")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBackend, rhs: rhsBackend, with: matcher), lhsBackend, rhsBackend, "backend")) - return Matcher.ComparisonResult(results) - - case (.m_login__ssoToken_ssoToken(let lhsSsotoken), .m_login__ssoToken_ssoToken(let rhsSsotoken)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSsotoken, rhs: rhsSsotoken, with: matcher), lhsSsotoken, rhsSsotoken, "ssoToken")) - return Matcher.ComparisonResult(results) - - case (.m_resetPassword__email_email(let lhsEmail), .m_resetPassword__email_email(let rhsEmail)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEmail, rhs: rhsEmail, with: matcher), lhsEmail, rhsEmail, "email")) - return Matcher.ComparisonResult(results) - - case (.m_getCookies__force_force(let lhsForce), .m_getCookies__force_force(let rhsForce)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsForce, rhs: rhsForce, with: matcher), lhsForce, rhsForce, "force")) - return Matcher.ComparisonResult(results) - - case (.m_getRegistrationFields, .m_getRegistrationFields): return .match - - case (.m_registerUser__fields_fieldsisSocial_isSocial(let lhsFields, let lhsIssocial), .m_registerUser__fields_fieldsisSocial_isSocial(let rhsFields, let rhsIssocial)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIssocial, rhs: rhsIssocial, with: matcher), lhsIssocial, rhsIssocial, "isSocial")) - return Matcher.ComparisonResult(results) - - case (.m_validateRegistrationFields__fields_fields(let lhsFields), .m_validateRegistrationFields__fields_fields(let rhsFields)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_login__username_usernamepassword_password(p0, p1): return p0.intValue + p1.intValue - case let .m_login__externalToken_externalTokenbackend_backend(p0, p1): return p0.intValue + p1.intValue - case let .m_login__ssoToken_ssoToken(p0): return p0.intValue - case let .m_resetPassword__email_email(p0): return p0.intValue - case let .m_getCookies__force_force(p0): return p0.intValue - case .m_getRegistrationFields: return 0 - case let .m_registerUser__fields_fieldsisSocial_isSocial(p0, p1): return p0.intValue + p1.intValue - case let .m_validateRegistrationFields__fields_fields(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_login__username_usernamepassword_password: return ".login(username:password:)" - case .m_login__externalToken_externalTokenbackend_backend: return ".login(externalToken:backend:)" - case .m_login__ssoToken_ssoToken: return ".login(ssoToken:)" - case .m_resetPassword__email_email: return ".resetPassword(email:)" - case .m_getCookies__force_force: return ".getCookies(force:)" - case .m_getRegistrationFields: return ".getRegistrationFields()" - case .m_registerUser__fields_fieldsisSocial_isSocial: return ".registerUser(fields:isSocial:)" - case .m_validateRegistrationFields__fields_fields: return ".validateRegistrationFields(fields:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - @discardableResult - public static func login(username: Parameter, password: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func login(ssoToken: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func resetPassword(email: Parameter, willReturn: ResetPassword...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getRegistrationFields(willReturn: [PickerFields]...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willReturn: [String: String]...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func login(ssoToken: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func login(ssoToken: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func resetPassword(email: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resetPassword(email: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (ResetPassword).self) - willProduce(stubber) - return given - } - public static func getCookies(force: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCookies(force: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func getRegistrationFields(willThrow: Error...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getRegistrationFields(willProduce: (StubberThrows<[PickerFields]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([PickerFields]).self) - willProduce(stubber) - return given - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willProduce: (StubberThrows<[String: String]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([String: String]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - @discardableResult - public static func login(username: Parameter, password: Parameter) -> Verify { return Verify(method: .m_login__username_usernamepassword_password(`username`, `password`))} - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter) -> Verify { return Verify(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`))} - public static func login(ssoToken: Parameter) -> Verify { return Verify(method: .m_login__ssoToken_ssoToken(`ssoToken`))} - public static func resetPassword(email: Parameter) -> Verify { return Verify(method: .m_resetPassword__email_email(`email`))} - public static func getCookies(force: Parameter) -> Verify { return Verify(method: .m_getCookies__force_force(`force`))} - public static func getRegistrationFields() -> Verify { return Verify(method: .m_getRegistrationFields)} - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter) -> Verify { return Verify(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`))} - public static func validateRegistrationFields(fields: Parameter<[String: String]>) -> Verify { return Verify(method: .m_validateRegistrationFields__fields_fields(`fields`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - @discardableResult - public static func login(username: Parameter, password: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__username_usernamepassword_password(`username`, `password`), performs: perform) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), performs: perform) - } - public static func login(ssoToken: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_login__ssoToken_ssoToken(`ssoToken`), performs: perform) - } - public static func resetPassword(email: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_resetPassword__email_email(`email`), performs: perform) - } - public static func getCookies(force: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_getCookies__force_force(`force`), performs: perform) - } - public static func getRegistrationFields(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getRegistrationFields, performs: perform) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, perform: @escaping ([String: String], Bool) -> Void) -> Perform { - return Perform(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), performs: perform) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, perform: @escaping ([String: String]) -> Void) -> Perform { - return Perform(method: .m_validateRegistrationFields__fields_fields(`fields`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - BaseRouter -@MainActor -open class BaseRouterMock: BaseRouter, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func backToRoot(animated: Bool) { - addInvocation(.m_backToRoot__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_backToRoot__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func back(animated: Bool) { - addInvocation(.m_back__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_back__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func backWithFade() { - addInvocation(.m_backWithFade) - let perform = methodPerformValue(.m_backWithFade) as? () -> Void - perform?() - } - - open func dismiss(animated: Bool) { - addInvocation(.m_dismiss__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_dismiss__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func removeLastView(controllers: Int) { - addInvocation(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) - let perform = methodPerformValue(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) as? (Int) -> Void - perform?(`controllers`) - } - - open func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { - addInvocation(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) - let perform = methodPerformValue(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) as? (LogistrationSourceScreen, PostLoginData?) -> Void - perform?(`sourceScreen`, `postLoginData`) - } - - open func showStartupScreen() { - addInvocation(.m_showStartupScreen) - let perform = methodPerformValue(.m_showStartupScreen) as? () -> Void - perform?() - } - - open func showLoginScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showForgotPasswordScreen() { - addInvocation(.m_showForgotPasswordScreen) - let perform = methodPerformValue(.m_showForgotPasswordScreen) as? () -> Void - perform?() - } - - open func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) as? (String?, LogistrationSourceScreen) -> Void - perform?(`searchQuery`, `sourceScreen`) - } - - open func showWebBrowser(title: String, url: URL) { - addInvocation(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) - let perform = methodPerformValue(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) as? (String, URL) -> Void - perform?(`title`, `url`) - } - - open func showSSOWebBrowser(title: String) { - addInvocation(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) - let perform = methodPerformValue(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) as? (String) -> Void - perform?(`title`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) as? (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void - perform?(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) as? (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void - perform?(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { - addInvocation(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) as? (UIModalTransitionStyle, any View, (() -> Void)?) -> Void - perform?(`transitionStyle`, `view`, `completion`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { - addInvocation(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) as? (UIModalTransitionStyle, Bool, () -> any View) -> Void - perform?(`transitionStyle`, `animated`, `content`) - } - - - fileprivate enum MethodType { - case m_backToRoot__animated_animated(Parameter) - case m_back__animated_animated(Parameter) - case m_backWithFade - case m_dismiss__animated_animated(Parameter) - case m_removeLastView__controllers_controllers(Parameter) - case m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter, Parameter) - case m_showStartupScreen - case m_showLoginScreen__sourceScreen_sourceScreen(Parameter) - case m_showRegisterScreen__sourceScreen_sourceScreen(Parameter) - case m_showForgotPasswordScreen - case m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter, Parameter) - case m_showWebBrowser__title_titleurl_url(Parameter, Parameter) - case m_showSSOWebBrowser__title_title(Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter<() -> Void>) - case m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter, Parameter, Parameter<(() -> Void)?>) - case m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter, Parameter, Parameter<() -> any View>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_backToRoot__animated_animated(let lhsAnimated), .m_backToRoot__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_back__animated_animated(let lhsAnimated), .m_back__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_backWithFade, .m_backWithFade): return .match - - case (.m_dismiss__animated_animated(let lhsAnimated), .m_dismiss__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_removeLastView__controllers_controllers(let lhsControllers), .m_removeLastView__controllers_controllers(let rhsControllers)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsControllers, rhs: rhsControllers, with: matcher), lhsControllers, rhsControllers, "controllers")) - return Matcher.ComparisonResult(results) - - case (.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let lhsSourcescreen, let lhsPostlogindata), .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let rhsSourcescreen, let rhsPostlogindata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPostlogindata, rhs: rhsPostlogindata, with: matcher), lhsPostlogindata, rhsPostlogindata, "postLoginData")) - return Matcher.ComparisonResult(results) - - case (.m_showStartupScreen, .m_showStartupScreen): return .match - - case (.m_showLoginScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showLoginScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showRegisterScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showRegisterScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showForgotPasswordScreen, .m_showForgotPasswordScreen): return .match - - case (.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let lhsSearchquery, let lhsSourcescreen), .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let rhsSearchquery, let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchquery, rhs: rhsSearchquery, with: matcher), lhsSearchquery, rhsSearchquery, "searchQuery")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showWebBrowser__title_titleurl_url(let lhsTitle, let lhsUrl), .m_showWebBrowser__title_titleurl_url(let rhsTitle, let rhsUrl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - return Matcher.ComparisonResult(results) - - case (.m_showSSOWebBrowser__title_title(let lhsTitle), .m_showSSOWebBrowser__title_title(let rhsTitle)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let lhsAlerttitle, let lhsAlertmessage, let lhsPositiveaction, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsType), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let rhsAlerttitle, let rhsAlertmessage, let rhsPositiveaction, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPositiveaction, rhs: rhsPositiveaction, with: matcher), lhsPositiveaction, rhsPositiveaction, "positiveAction")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let lhsAlerttitle, let lhsAlertmessage, let lhsNextsectionname, let lhsAction, let lhsImage, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsNextsectiontapped), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let rhsAlerttitle, let rhsAlertmessage, let rhsNextsectionname, let rhsAction, let rhsImage, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsNextsectiontapped)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectionname, rhs: rhsNextsectionname, with: matcher), lhsNextsectionname, rhsNextsectionname, "nextSectionName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsImage, rhs: rhsImage, with: matcher), lhsImage, rhsImage, "image")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectiontapped, rhs: rhsNextsectiontapped, with: matcher), lhsNextsectiontapped, rhsNextsectiontapped, "nextSectionTapped")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let lhsTransitionstyle, let lhsView, let lhsCompletion), .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let rhsTransitionstyle, let rhsView, let rhsCompletion)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsView, rhs: rhsView, with: matcher), lhsView, rhsView, "view")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCompletion, rhs: rhsCompletion, with: matcher), lhsCompletion, rhsCompletion, "completion")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let lhsTransitionstyle, let lhsAnimated, let lhsContent), .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let rhsTransitionstyle, let rhsAnimated, let rhsContent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsContent, rhs: rhsContent, with: matcher), lhsContent, rhsContent, "content")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_backToRoot__animated_animated(p0): return p0.intValue - case let .m_back__animated_animated(p0): return p0.intValue - case .m_backWithFade: return 0 - case let .m_dismiss__animated_animated(p0): return p0.intValue - case let .m_removeLastView__controllers_controllers(p0): return p0.intValue - case let .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(p0, p1): return p0.intValue + p1.intValue - case .m_showStartupScreen: return 0 - case let .m_showLoginScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case let .m_showRegisterScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case .m_showForgotPasswordScreen: return 0 - case let .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(p0, p1): return p0.intValue + p1.intValue - case let .m_showWebBrowser__title_titleurl_url(p0, p1): return p0.intValue + p1.intValue - case let .m_showSSOWebBrowser__title_title(p0): return p0.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(p0, p1, p2, p3, p4, p5, p6, p7): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue + p7.intValue - case let .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_backToRoot__animated_animated: return ".backToRoot(animated:)" - case .m_back__animated_animated: return ".back(animated:)" - case .m_backWithFade: return ".backWithFade()" - case .m_dismiss__animated_animated: return ".dismiss(animated:)" - case .m_removeLastView__controllers_controllers: return ".removeLastView(controllers:)" - case .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData: return ".showMainOrWhatsNewScreen(sourceScreen:postLoginData:)" - case .m_showStartupScreen: return ".showStartupScreen()" - case .m_showLoginScreen__sourceScreen_sourceScreen: return ".showLoginScreen(sourceScreen:)" - case .m_showRegisterScreen__sourceScreen_sourceScreen: return ".showRegisterScreen(sourceScreen:)" - case .m_showForgotPasswordScreen: return ".showForgotPasswordScreen()" - case .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen: return ".showDiscoveryScreen(searchQuery:sourceScreen:)" - case .m_showWebBrowser__title_titleurl_url: return ".showWebBrowser(title:url:)" - case .m_showSSOWebBrowser__title_title: return ".showSSOWebBrowser(title:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type: return ".presentAlert(alertTitle:alertMessage:positiveAction:onCloseTapped:firstButtonTapped:type:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped: return ".presentAlert(alertTitle:alertMessage:nextSectionName:action:image:onCloseTapped:firstButtonTapped:nextSectionTapped:)" - case .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion: return ".presentView(transitionStyle:view:completion:)" - case .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content: return ".presentView(transitionStyle:animated:content:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func backToRoot(animated: Parameter) -> Verify { return Verify(method: .m_backToRoot__animated_animated(`animated`))} - public static func back(animated: Parameter) -> Verify { return Verify(method: .m_back__animated_animated(`animated`))} - public static func backWithFade() -> Verify { return Verify(method: .m_backWithFade)} - public static func dismiss(animated: Parameter) -> Verify { return Verify(method: .m_dismiss__animated_animated(`animated`))} - public static func removeLastView(controllers: Parameter) -> Verify { return Verify(method: .m_removeLastView__controllers_controllers(`controllers`))} - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter) -> Verify { return Verify(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`))} - public static func showStartupScreen() -> Verify { return Verify(method: .m_showStartupScreen)} - public static func showLoginScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showRegisterScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showForgotPasswordScreen() -> Verify { return Verify(method: .m_showForgotPasswordScreen)} - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter) -> Verify { return Verify(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`))} - public static func showWebBrowser(title: Parameter, url: Parameter) -> Verify { return Verify(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`))} - public static func showSSOWebBrowser(title: Parameter) -> Verify { return Verify(method: .m_showSSOWebBrowser__title_title(`title`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`))} - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`))} - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func backToRoot(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_backToRoot__animated_animated(`animated`), performs: perform) - } - public static func back(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_back__animated_animated(`animated`), performs: perform) - } - public static func backWithFade(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_backWithFade, performs: perform) - } - public static func dismiss(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_dismiss__animated_animated(`animated`), performs: perform) - } - public static func removeLastView(controllers: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_removeLastView__controllers_controllers(`controllers`), performs: perform) - } - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter, perform: @escaping (LogistrationSourceScreen, PostLoginData?) -> Void) -> Perform { - return Perform(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`), performs: perform) - } - public static func showStartupScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showStartupScreen, performs: perform) - } - public static func showLoginScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showRegisterScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showForgotPasswordScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showForgotPasswordScreen, performs: perform) - } - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter, perform: @escaping (String?, LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`), performs: perform) - } - public static func showWebBrowser(title: Parameter, url: Parameter, perform: @escaping (String, URL) -> Void) -> Perform { - return Perform(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`), performs: perform) - } - public static func showSSOWebBrowser(title: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showSSOWebBrowser__title_title(`title`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter, perform: @escaping (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>, perform: @escaping (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>, perform: @escaping (UIModalTransitionStyle, any View, (() -> Void)?) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>, perform: @escaping (UIModalTransitionStyle, Bool, () -> any View) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CalendarManagerProtocol -@MainActor -open class CalendarManagerProtocolMock: CalendarManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func createCalendarIfNeeded() { - addInvocation(.m_createCalendarIfNeeded) - let perform = methodPerformValue(.m_createCalendarIfNeeded) as? () -> Void - perform?() - } - - open func filterCoursesBySelected(fetchedCourses: [CourseForSync]) -> [CourseForSync] { - addInvocation(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) - let perform = methodPerformValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) as? ([CourseForSync]) -> Void - perform?(`fetchedCourses`) - var __value: [CourseForSync] - do { - __value = try methodReturnValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))).casted() - } catch { - onFatalFailure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - Failure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - } - return __value - } - - open func removeOldCalendar() { - addInvocation(.m_removeOldCalendar) - let perform = methodPerformValue(.m_removeOldCalendar) as? () -> Void - perform?() - } - - open func removeOutdatedEvents(courseID: String) { - addInvocation(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - } - - open func syncCourse(courseID: String, courseName: String, dates: CourseDates) { - addInvocation(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) - let perform = methodPerformValue(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) as? (String, String, CourseDates) -> Void - perform?(`courseID`, `courseName`, `dates`) - } - - open func requestAccess() -> Bool { - addInvocation(.m_requestAccess) - let perform = methodPerformValue(.m_requestAccess) as? () -> Void - perform?() - var __value: Bool - do { - __value = try methodReturnValue(.m_requestAccess).casted() - } catch { - onFatalFailure("Stub return value not specified for requestAccess(). Use given") - Failure("Stub return value not specified for requestAccess(). Use given") - } - return __value - } - - open func courseStatus(courseID: String) -> SyncStatus { - addInvocation(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: SyncStatus - do { - __value = try methodReturnValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for courseStatus(courseID: String). Use given") - Failure("Stub return value not specified for courseStatus(courseID: String). Use given") - } - return __value - } - - open func clearAllData(removeCalendar: Bool) { - addInvocation(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) - let perform = methodPerformValue(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) as? (Bool) -> Void - perform?(`removeCalendar`) - } - - open func isDatesChanged(courseID: String, checksum: String) -> Bool { - addInvocation(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) - let perform = methodPerformValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) as? (String, String) -> Void - perform?(`courseID`, `checksum`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - Failure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - } - return __value - } - - - fileprivate enum MethodType { - case m_createCalendarIfNeeded - case m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>) - case m_removeOldCalendar - case m_removeOutdatedEvents__courseID_courseID(Parameter) - case m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter, Parameter, Parameter) - case m_requestAccess - case m_courseStatus__courseID_courseID(Parameter) - case m_clearAllData__removeCalendar_removeCalendar(Parameter) - case m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_createCalendarIfNeeded, .m_createCalendarIfNeeded): return .match - - case (.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let lhsFetchedcourses), .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let rhsFetchedcourses)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFetchedcourses, rhs: rhsFetchedcourses, with: matcher), lhsFetchedcourses, rhsFetchedcourses, "fetchedCourses")) - return Matcher.ComparisonResult(results) - - case (.m_removeOldCalendar, .m_removeOldCalendar): return .match - - case (.m_removeOutdatedEvents__courseID_courseID(let lhsCourseid), .m_removeOutdatedEvents__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let lhsCourseid, let lhsCoursename, let lhsDates), .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let rhsCourseid, let rhsCoursename, let rhsDates)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDates, rhs: rhsDates, with: matcher), lhsDates, rhsDates, "dates")) - return Matcher.ComparisonResult(results) - - case (.m_requestAccess, .m_requestAccess): return .match - - case (.m_courseStatus__courseID_courseID(let lhsCourseid), .m_courseStatus__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_clearAllData__removeCalendar_removeCalendar(let lhsRemovecalendar), .m_clearAllData__removeCalendar_removeCalendar(let rhsRemovecalendar)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRemovecalendar, rhs: rhsRemovecalendar, with: matcher), lhsRemovecalendar, rhsRemovecalendar, "removeCalendar")) - return Matcher.ComparisonResult(results) - - case (.m_isDatesChanged__courseID_courseIDchecksum_checksum(let lhsCourseid, let lhsChecksum), .m_isDatesChanged__courseID_courseIDchecksum_checksum(let rhsCourseid, let rhsChecksum)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsChecksum, rhs: rhsChecksum, with: matcher), lhsChecksum, rhsChecksum, "checksum")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_createCalendarIfNeeded: return 0 - case let .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(p0): return p0.intValue - case .m_removeOldCalendar: return 0 - case let .m_removeOutdatedEvents__courseID_courseID(p0): return p0.intValue - case let .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case .m_requestAccess: return 0 - case let .m_courseStatus__courseID_courseID(p0): return p0.intValue - case let .m_clearAllData__removeCalendar_removeCalendar(p0): return p0.intValue - case let .m_isDatesChanged__courseID_courseIDchecksum_checksum(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_createCalendarIfNeeded: return ".createCalendarIfNeeded()" - case .m_filterCoursesBySelected__fetchedCourses_fetchedCourses: return ".filterCoursesBySelected(fetchedCourses:)" - case .m_removeOldCalendar: return ".removeOldCalendar()" - case .m_removeOutdatedEvents__courseID_courseID: return ".removeOutdatedEvents(courseID:)" - case .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates: return ".syncCourse(courseID:courseName:dates:)" - case .m_requestAccess: return ".requestAccess()" - case .m_courseStatus__courseID_courseID: return ".courseStatus(courseID:)" - case .m_clearAllData__removeCalendar_removeCalendar: return ".clearAllData(removeCalendar:)" - case .m_isDatesChanged__courseID_courseIDchecksum_checksum: return ".isDatesChanged(courseID:checksum:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willReturn: [CourseForSync]...) -> MethodStub { - return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func requestAccess(willReturn: Bool...) -> MethodStub { - return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func courseStatus(courseID: Parameter, willReturn: SyncStatus...) -> MethodStub { - return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willProduce: (Stubber<[CourseForSync]>) -> Void) -> MethodStub { - let willReturn: [[CourseForSync]] = [] - let given: Given = { return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([CourseForSync]).self) - willProduce(stubber) - return given - } - public static func requestAccess(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func courseStatus(courseID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [SyncStatus] = [] - let given: Given = { return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (SyncStatus).self) - willProduce(stubber) - return given - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func createCalendarIfNeeded() -> Verify { return Verify(method: .m_createCalendarIfNeeded)} - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>) -> Verify { return Verify(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`))} - public static func removeOldCalendar() -> Verify { return Verify(method: .m_removeOldCalendar)} - public static func removeOutdatedEvents(courseID: Parameter) -> Verify { return Verify(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`))} - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter) -> Verify { return Verify(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`))} - public static func requestAccess() -> Verify { return Verify(method: .m_requestAccess)} - public static func courseStatus(courseID: Parameter) -> Verify { return Verify(method: .m_courseStatus__courseID_courseID(`courseID`))} - public static func clearAllData(removeCalendar: Parameter) -> Verify { return Verify(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`))} - public static func isDatesChanged(courseID: Parameter, checksum: Parameter) -> Verify { return Verify(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func createCalendarIfNeeded(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_createCalendarIfNeeded, performs: perform) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, perform: @escaping ([CourseForSync]) -> Void) -> Perform { - return Perform(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), performs: perform) - } - public static func removeOldCalendar(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeOldCalendar, performs: perform) - } - public static func removeOutdatedEvents(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`), performs: perform) - } - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter, perform: @escaping (String, String, CourseDates) -> Void) -> Perform { - return Perform(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`), performs: perform) - } - public static func requestAccess(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_requestAccess, performs: perform) - } - public static func courseStatus(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_courseStatus__courseID_courseID(`courseID`), performs: perform) - } - public static func clearAllData(removeCalendar: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`), performs: perform) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConfigProtocol - -open class ConfigProtocolMock: ConfigProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var baseURL: URL { - get { invocations.append(.p_baseURL_get); return __p_baseURL ?? givenGetterValue(.p_baseURL_get, "ConfigProtocolMock - stub value for baseURL was not defined") } - } - private var __p_baseURL: (URL)? - - public var baseSSOURL: URL { - get { invocations.append(.p_baseSSOURL_get); return __p_baseSSOURL ?? givenGetterValue(.p_baseSSOURL_get, "ConfigProtocolMock - stub value for baseSSOURL was not defined") } - } - private var __p_baseSSOURL: (URL)? - - public var ssoFinishedURL: URL { - get { invocations.append(.p_ssoFinishedURL_get); return __p_ssoFinishedURL ?? givenGetterValue(.p_ssoFinishedURL_get, "ConfigProtocolMock - stub value for ssoFinishedURL was not defined") } - } - private var __p_ssoFinishedURL: (URL)? - - public var ssoButtonTitle: [String: Any] { - get { invocations.append(.p_ssoButtonTitle_get); return __p_ssoButtonTitle ?? givenGetterValue(.p_ssoButtonTitle_get, "ConfigProtocolMock - stub value for ssoButtonTitle was not defined") } - } - private var __p_ssoButtonTitle: ([String: Any])? - - public var oAuthClientId: String { - get { invocations.append(.p_oAuthClientId_get); return __p_oAuthClientId ?? givenGetterValue(.p_oAuthClientId_get, "ConfigProtocolMock - stub value for oAuthClientId was not defined") } - } - private var __p_oAuthClientId: (String)? - - public var tokenType: TokenType { - get { invocations.append(.p_tokenType_get); return __p_tokenType ?? givenGetterValue(.p_tokenType_get, "ConfigProtocolMock - stub value for tokenType was not defined") } - } - private var __p_tokenType: (TokenType)? - - public var feedbackEmail: String { - get { invocations.append(.p_feedbackEmail_get); return __p_feedbackEmail ?? givenGetterValue(.p_feedbackEmail_get, "ConfigProtocolMock - stub value for feedbackEmail was not defined") } - } - private var __p_feedbackEmail: (String)? - - public var appStoreLink: String { - get { invocations.append(.p_appStoreLink_get); return __p_appStoreLink ?? givenGetterValue(.p_appStoreLink_get, "ConfigProtocolMock - stub value for appStoreLink was not defined") } - } - private var __p_appStoreLink: (String)? - - public var faq: URL? { - get { invocations.append(.p_faq_get); return __p_faq ?? optionalGivenGetterValue(.p_faq_get, "ConfigProtocolMock - stub value for faq was not defined") } - } - private var __p_faq: (URL)? - - public var platformName: String { - get { invocations.append(.p_platformName_get); return __p_platformName ?? givenGetterValue(.p_platformName_get, "ConfigProtocolMock - stub value for platformName was not defined") } - } - private var __p_platformName: (String)? - - public var agreement: AgreementConfig { - get { invocations.append(.p_agreement_get); return __p_agreement ?? givenGetterValue(.p_agreement_get, "ConfigProtocolMock - stub value for agreement was not defined") } - } - private var __p_agreement: (AgreementConfig)? - - public var firebase: FirebaseConfig { - get { invocations.append(.p_firebase_get); return __p_firebase ?? givenGetterValue(.p_firebase_get, "ConfigProtocolMock - stub value for firebase was not defined") } - } - private var __p_firebase: (FirebaseConfig)? - - public var facebook: FacebookConfig { - get { invocations.append(.p_facebook_get); return __p_facebook ?? givenGetterValue(.p_facebook_get, "ConfigProtocolMock - stub value for facebook was not defined") } - } - private var __p_facebook: (FacebookConfig)? - - public var microsoft: MicrosoftConfig { - get { invocations.append(.p_microsoft_get); return __p_microsoft ?? givenGetterValue(.p_microsoft_get, "ConfigProtocolMock - stub value for microsoft was not defined") } - } - private var __p_microsoft: (MicrosoftConfig)? - - public var google: GoogleConfig { - get { invocations.append(.p_google_get); return __p_google ?? givenGetterValue(.p_google_get, "ConfigProtocolMock - stub value for google was not defined") } - } - private var __p_google: (GoogleConfig)? - - public var appleSignIn: AppleSignInConfig { - get { invocations.append(.p_appleSignIn_get); return __p_appleSignIn ?? givenGetterValue(.p_appleSignIn_get, "ConfigProtocolMock - stub value for appleSignIn was not defined") } - } - private var __p_appleSignIn: (AppleSignInConfig)? - - public var features: FeaturesConfig { - get { invocations.append(.p_features_get); return __p_features ?? givenGetterValue(.p_features_get, "ConfigProtocolMock - stub value for features was not defined") } - } - private var __p_features: (FeaturesConfig)? - - public var theme: ThemeConfig { - get { invocations.append(.p_theme_get); return __p_theme ?? givenGetterValue(.p_theme_get, "ConfigProtocolMock - stub value for theme was not defined") } - } - private var __p_theme: (ThemeConfig)? - - public var uiComponents: UIComponentsConfig { - get { invocations.append(.p_uiComponents_get); return __p_uiComponents ?? givenGetterValue(.p_uiComponents_get, "ConfigProtocolMock - stub value for uiComponents was not defined") } - } - private var __p_uiComponents: (UIComponentsConfig)? - - public var discovery: DiscoveryConfig { - get { invocations.append(.p_discovery_get); return __p_discovery ?? givenGetterValue(.p_discovery_get, "ConfigProtocolMock - stub value for discovery was not defined") } - } - private var __p_discovery: (DiscoveryConfig)? - - public var dashboard: DashboardConfig { - get { invocations.append(.p_dashboard_get); return __p_dashboard ?? givenGetterValue(.p_dashboard_get, "ConfigProtocolMock - stub value for dashboard was not defined") } - } - private var __p_dashboard: (DashboardConfig)? - - public var braze: BrazeConfig { - get { invocations.append(.p_braze_get); return __p_braze ?? givenGetterValue(.p_braze_get, "ConfigProtocolMock - stub value for braze was not defined") } - } - private var __p_braze: (BrazeConfig)? - - public var branch: BranchConfig { - get { invocations.append(.p_branch_get); return __p_branch ?? givenGetterValue(.p_branch_get, "ConfigProtocolMock - stub value for branch was not defined") } - } - private var __p_branch: (BranchConfig)? - - public var program: DiscoveryConfig { - get { invocations.append(.p_program_get); return __p_program ?? givenGetterValue(.p_program_get, "ConfigProtocolMock - stub value for program was not defined") } - } - private var __p_program: (DiscoveryConfig)? - - public var experimentalFeatures: ExperimentalFeaturesConfig { - get { invocations.append(.p_experimentalFeatures_get); return __p_experimentalFeatures ?? givenGetterValue(.p_experimentalFeatures_get, "ConfigProtocolMock - stub value for experimentalFeatures was not defined") } - } - private var __p_experimentalFeatures: (ExperimentalFeaturesConfig)? - - public var URIScheme: String { - get { invocations.append(.p_URIScheme_get); return __p_URIScheme ?? givenGetterValue(.p_URIScheme_get, "ConfigProtocolMock - stub value for URIScheme was not defined") } - } - private var __p_URIScheme: (String)? - - - - - - - fileprivate enum MethodType { - case p_baseURL_get - case p_baseSSOURL_get - case p_ssoFinishedURL_get - case p_ssoButtonTitle_get - case p_oAuthClientId_get - case p_tokenType_get - case p_feedbackEmail_get - case p_appStoreLink_get - case p_faq_get - case p_platformName_get - case p_agreement_get - case p_firebase_get - case p_facebook_get - case p_microsoft_get - case p_google_get - case p_appleSignIn_get - case p_features_get - case p_theme_get - case p_uiComponents_get - case p_discovery_get - case p_dashboard_get - case p_braze_get - case p_branch_get - case p_program_get - case p_experimentalFeatures_get - case p_URIScheme_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_baseURL_get,.p_baseURL_get): return Matcher.ComparisonResult.match - case (.p_baseSSOURL_get,.p_baseSSOURL_get): return Matcher.ComparisonResult.match - case (.p_ssoFinishedURL_get,.p_ssoFinishedURL_get): return Matcher.ComparisonResult.match - case (.p_ssoButtonTitle_get,.p_ssoButtonTitle_get): return Matcher.ComparisonResult.match - case (.p_oAuthClientId_get,.p_oAuthClientId_get): return Matcher.ComparisonResult.match - case (.p_tokenType_get,.p_tokenType_get): return Matcher.ComparisonResult.match - case (.p_feedbackEmail_get,.p_feedbackEmail_get): return Matcher.ComparisonResult.match - case (.p_appStoreLink_get,.p_appStoreLink_get): return Matcher.ComparisonResult.match - case (.p_faq_get,.p_faq_get): return Matcher.ComparisonResult.match - case (.p_platformName_get,.p_platformName_get): return Matcher.ComparisonResult.match - case (.p_agreement_get,.p_agreement_get): return Matcher.ComparisonResult.match - case (.p_firebase_get,.p_firebase_get): return Matcher.ComparisonResult.match - case (.p_facebook_get,.p_facebook_get): return Matcher.ComparisonResult.match - case (.p_microsoft_get,.p_microsoft_get): return Matcher.ComparisonResult.match - case (.p_google_get,.p_google_get): return Matcher.ComparisonResult.match - case (.p_appleSignIn_get,.p_appleSignIn_get): return Matcher.ComparisonResult.match - case (.p_features_get,.p_features_get): return Matcher.ComparisonResult.match - case (.p_theme_get,.p_theme_get): return Matcher.ComparisonResult.match - case (.p_uiComponents_get,.p_uiComponents_get): return Matcher.ComparisonResult.match - case (.p_discovery_get,.p_discovery_get): return Matcher.ComparisonResult.match - case (.p_dashboard_get,.p_dashboard_get): return Matcher.ComparisonResult.match - case (.p_braze_get,.p_braze_get): return Matcher.ComparisonResult.match - case (.p_branch_get,.p_branch_get): return Matcher.ComparisonResult.match - case (.p_program_get,.p_program_get): return Matcher.ComparisonResult.match - case (.p_experimentalFeatures_get,.p_experimentalFeatures_get): return Matcher.ComparisonResult.match - case (.p_URIScheme_get,.p_URIScheme_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_baseURL_get: return 0 - case .p_baseSSOURL_get: return 0 - case .p_ssoFinishedURL_get: return 0 - case .p_ssoButtonTitle_get: return 0 - case .p_oAuthClientId_get: return 0 - case .p_tokenType_get: return 0 - case .p_feedbackEmail_get: return 0 - case .p_appStoreLink_get: return 0 - case .p_faq_get: return 0 - case .p_platformName_get: return 0 - case .p_agreement_get: return 0 - case .p_firebase_get: return 0 - case .p_facebook_get: return 0 - case .p_microsoft_get: return 0 - case .p_google_get: return 0 - case .p_appleSignIn_get: return 0 - case .p_features_get: return 0 - case .p_theme_get: return 0 - case .p_uiComponents_get: return 0 - case .p_discovery_get: return 0 - case .p_dashboard_get: return 0 - case .p_braze_get: return 0 - case .p_branch_get: return 0 - case .p_program_get: return 0 - case .p_experimentalFeatures_get: return 0 - case .p_URIScheme_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_baseURL_get: return "[get] .baseURL" - case .p_baseSSOURL_get: return "[get] .baseSSOURL" - case .p_ssoFinishedURL_get: return "[get] .ssoFinishedURL" - case .p_ssoButtonTitle_get: return "[get] .ssoButtonTitle" - case .p_oAuthClientId_get: return "[get] .oAuthClientId" - case .p_tokenType_get: return "[get] .tokenType" - case .p_feedbackEmail_get: return "[get] .feedbackEmail" - case .p_appStoreLink_get: return "[get] .appStoreLink" - case .p_faq_get: return "[get] .faq" - case .p_platformName_get: return "[get] .platformName" - case .p_agreement_get: return "[get] .agreement" - case .p_firebase_get: return "[get] .firebase" - case .p_facebook_get: return "[get] .facebook" - case .p_microsoft_get: return "[get] .microsoft" - case .p_google_get: return "[get] .google" - case .p_appleSignIn_get: return "[get] .appleSignIn" - case .p_features_get: return "[get] .features" - case .p_theme_get: return "[get] .theme" - case .p_uiComponents_get: return "[get] .uiComponents" - case .p_discovery_get: return "[get] .discovery" - case .p_dashboard_get: return "[get] .dashboard" - case .p_braze_get: return "[get] .braze" - case .p_branch_get: return "[get] .branch" - case .p_program_get: return "[get] .program" - case .p_experimentalFeatures_get: return "[get] .experimentalFeatures" - case .p_URIScheme_get: return "[get] .URIScheme" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func baseURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func baseSSOURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseSSOURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoFinishedURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_ssoFinishedURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoButtonTitle(getter defaultValue: [String: Any]...) -> PropertyStub { - return Given(method: .p_ssoButtonTitle_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func oAuthClientId(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_oAuthClientId_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func tokenType(getter defaultValue: TokenType...) -> PropertyStub { - return Given(method: .p_tokenType_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func feedbackEmail(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_feedbackEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appStoreLink(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_appStoreLink_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func faq(getter defaultValue: URL?...) -> PropertyStub { - return Given(method: .p_faq_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func platformName(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_platformName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func agreement(getter defaultValue: AgreementConfig...) -> PropertyStub { - return Given(method: .p_agreement_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func firebase(getter defaultValue: FirebaseConfig...) -> PropertyStub { - return Given(method: .p_firebase_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func facebook(getter defaultValue: FacebookConfig...) -> PropertyStub { - return Given(method: .p_facebook_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func microsoft(getter defaultValue: MicrosoftConfig...) -> PropertyStub { - return Given(method: .p_microsoft_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func google(getter defaultValue: GoogleConfig...) -> PropertyStub { - return Given(method: .p_google_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignIn(getter defaultValue: AppleSignInConfig...) -> PropertyStub { - return Given(method: .p_appleSignIn_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func features(getter defaultValue: FeaturesConfig...) -> PropertyStub { - return Given(method: .p_features_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func theme(getter defaultValue: ThemeConfig...) -> PropertyStub { - return Given(method: .p_theme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func uiComponents(getter defaultValue: UIComponentsConfig...) -> PropertyStub { - return Given(method: .p_uiComponents_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func discovery(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_discovery_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func dashboard(getter defaultValue: DashboardConfig...) -> PropertyStub { - return Given(method: .p_dashboard_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func braze(getter defaultValue: BrazeConfig...) -> PropertyStub { - return Given(method: .p_braze_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func branch(getter defaultValue: BranchConfig...) -> PropertyStub { - return Given(method: .p_branch_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func program(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_program_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func experimentalFeatures(getter defaultValue: ExperimentalFeaturesConfig...) -> PropertyStub { - return Given(method: .p_experimentalFeatures_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func URIScheme(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_URIScheme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var baseURL: Verify { return Verify(method: .p_baseURL_get) } - public static var baseSSOURL: Verify { return Verify(method: .p_baseSSOURL_get) } - public static var ssoFinishedURL: Verify { return Verify(method: .p_ssoFinishedURL_get) } - public static var ssoButtonTitle: Verify { return Verify(method: .p_ssoButtonTitle_get) } - public static var oAuthClientId: Verify { return Verify(method: .p_oAuthClientId_get) } - public static var tokenType: Verify { return Verify(method: .p_tokenType_get) } - public static var feedbackEmail: Verify { return Verify(method: .p_feedbackEmail_get) } - public static var appStoreLink: Verify { return Verify(method: .p_appStoreLink_get) } - public static var faq: Verify { return Verify(method: .p_faq_get) } - public static var platformName: Verify { return Verify(method: .p_platformName_get) } - public static var agreement: Verify { return Verify(method: .p_agreement_get) } - public static var firebase: Verify { return Verify(method: .p_firebase_get) } - public static var facebook: Verify { return Verify(method: .p_facebook_get) } - public static var microsoft: Verify { return Verify(method: .p_microsoft_get) } - public static var google: Verify { return Verify(method: .p_google_get) } - public static var appleSignIn: Verify { return Verify(method: .p_appleSignIn_get) } - public static var features: Verify { return Verify(method: .p_features_get) } - public static var theme: Verify { return Verify(method: .p_theme_get) } - public static var uiComponents: Verify { return Verify(method: .p_uiComponents_get) } - public static var discovery: Verify { return Verify(method: .p_discovery_get) } - public static var dashboard: Verify { return Verify(method: .p_dashboard_get) } - public static var braze: Verify { return Verify(method: .p_braze_get) } - public static var branch: Verify { return Verify(method: .p_branch_get) } - public static var program: Verify { return Verify(method: .p_program_get) } - public static var experimentalFeatures: Verify { return Verify(method: .p_experimentalFeatures_get) } - public static var URIScheme: Verify { return Verify(method: .p_URIScheme_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConnectivityProtocol -@MainActor -open class ConnectivityProtocolMock: ConnectivityProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var isInternetAvaliable: Bool { - get { invocations.append(.p_isInternetAvaliable_get); return __p_isInternetAvaliable ?? givenGetterValue(.p_isInternetAvaliable_get, "ConnectivityProtocolMock - stub value for isInternetAvaliable was not defined") } - } - private var __p_isInternetAvaliable: (Bool)? - - public var isMobileData: Bool { - get { invocations.append(.p_isMobileData_get); return __p_isMobileData ?? givenGetterValue(.p_isMobileData_get, "ConnectivityProtocolMock - stub value for isMobileData was not defined") } - } - private var __p_isMobileData: (Bool)? - - public var internetReachableSubject: CurrentValueSubject { - get { invocations.append(.p_internetReachableSubject_get); return __p_internetReachableSubject ?? givenGetterValue(.p_internetReachableSubject_get, "ConnectivityProtocolMock - stub value for internetReachableSubject was not defined") } - } - private var __p_internetReachableSubject: (CurrentValueSubject)? - - - - - - - fileprivate enum MethodType { - case p_isInternetAvaliable_get - case p_isMobileData_get - case p_internetReachableSubject_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_isInternetAvaliable_get,.p_isInternetAvaliable_get): return Matcher.ComparisonResult.match - case (.p_isMobileData_get,.p_isMobileData_get): return Matcher.ComparisonResult.match - case (.p_internetReachableSubject_get,.p_internetReachableSubject_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_isInternetAvaliable_get: return 0 - case .p_isMobileData_get: return 0 - case .p_internetReachableSubject_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_isInternetAvaliable_get: return "[get] .isInternetAvaliable" - case .p_isMobileData_get: return "[get] .isMobileData" - case .p_internetReachableSubject_get: return "[get] .internetReachableSubject" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func isInternetAvaliable(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isInternetAvaliable_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func isMobileData(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isMobileData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func internetReachableSubject(getter defaultValue: CurrentValueSubject...) -> PropertyStub { - return Given(method: .p_internetReachableSubject_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var isInternetAvaliable: Verify { return Verify(method: .p_isInternetAvaliable_get) } - public static var isMobileData: Verify { return Verify(method: .p_isMobileData_get) } - public static var internetReachableSubject: Verify { return Verify(method: .p_internetReachableSubject_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreAnalytics - -open class CoreAnalyticsMock: CoreAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { - addInvocation(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) - let perform = methodPerformValue(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) as? (AnalyticsEvent, EventBIValue, String?, Int?) -> Void - perform?(`event`, `biValue`, `action`, `rating`) - } - - open func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { - addInvocation(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) - let perform = methodPerformValue(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) as? (AnalyticsEvent, EventBIValue, String, String) -> Void - perform?(`event`, `bivalue`, `value`, `oldValue`) - } - - open func trackEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackScreenEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackScreenEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - - fileprivate enum MethodType { - case m_trackEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter, Parameter, Parameter, Parameter) - case m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter, Parameter, Parameter, Parameter) - case m_trackEvent__event(Parameter) - case m_trackEvent__eventbiValue_biValue(Parameter, Parameter) - case m_trackScreenEvent__event(Parameter) - case m_trackScreenEvent__eventbiValue_biValue(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_trackEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackScreenEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_appreview__eventbiValue_biValueaction_actionrating_rating(let lhsEvent, let lhsBivalue, let lhsAction, let lhsRating), .m_appreview__eventbiValue_biValueaction_actionrating_rating(let rhsEvent, let rhsBivalue, let rhsAction, let rhsRating)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRating, rhs: rhsRating, with: matcher), lhsRating, rhsRating, "rating")) - return Matcher.ComparisonResult(results) - - case (.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let lhsEvent, let lhsBivalue, let lhsValue, let lhsOldvalue), .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let rhsEvent, let rhsBivalue, let rhsValue, let rhsOldvalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "bivalue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsValue, rhs: rhsValue, with: matcher), lhsValue, rhsValue, "value")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOldvalue, rhs: rhsOldvalue, with: matcher), lhsOldvalue, rhsOldvalue, "oldValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__event(let lhsEvent), .m_trackEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__event(let lhsEvent), .m_trackScreenEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackScreenEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_trackEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_trackScreenEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_appreview__eventbiValue_biValueaction_actionrating_rating(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_trackEvent__event(p0): return p0.intValue - case let .m_trackEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__event(p0): return p0.intValue - case let .m_trackScreenEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_trackEvent__eventparameters_parameters: return ".trackEvent(_:parameters:)" - case .m_trackEvent__eventbiValue_biValueparameters_parameters: return ".trackEvent(_:biValue:parameters:)" - case .m_trackScreenEvent__eventparameters_parameters: return ".trackScreenEvent(_:parameters:)" - case .m_trackScreenEvent__eventbiValue_biValueparameters_parameters: return ".trackScreenEvent(_:biValue:parameters:)" - case .m_appreview__eventbiValue_biValueaction_actionrating_rating: return ".appreview(_:biValue:action:rating:)" - case .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue: return ".videoQualityChanged(_:bivalue:value:oldValue:)" - case .m_trackEvent__event: return ".trackEvent(_:)" - case .m_trackEvent__eventbiValue_biValue: return ".trackEvent(_:biValue:)" - case .m_trackScreenEvent__event: return ".trackScreenEvent(_:)" - case .m_trackScreenEvent__eventbiValue_biValue: return ".trackScreenEvent(_:biValue:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter) -> Verify { return Verify(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`))} - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter) -> Verify { return Verify(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`))} - public static func trackEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackEvent__event(`event`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`))} - public static func trackScreenEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__event(`event`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String?, Int?) -> Void) -> Perform { - return Perform(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`), performs: perform) - } - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String, String) -> Void) -> Perform { - return Perform(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`), performs: perform) - } - public static func trackEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackEvent__event(`event`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__event(`event`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CorePersistenceProtocol - -open class CorePersistenceProtocolMock: CorePersistenceProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func set(userId: Int) { - addInvocation(.m_set__userId_userId(Parameter.value(`userId`))) - let perform = methodPerformValue(.m_set__userId_userId(Parameter.value(`userId`))) as? (Int) -> Void - perform?(`userId`) - } - - open func getUserID() -> Int? { - addInvocation(.m_getUserID) - let perform = methodPerformValue(.m_getUserID) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getUserID).casted() - } catch { - // do nothing - } - return __value - } - - @MainActor - open func publisher() throws -> AnyPublisher { - addInvocation(.m_publisher) - let perform = methodPerformValue(.m_publisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_publisher).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for publisher(). Use given") - Failure("Stub return value not specified for publisher(). Use given") - } catch { - throw error - } - return __value - } - - open func addToDownloadQueue(tasks: [DownloadDataTask]) { - addInvocation(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) as? ([DownloadDataTask]) -> Void - perform?(`tasks`) - } - - open func saveOfflineProgress(progress: OfflineProgress) { - addInvocation(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) - let perform = methodPerformValue(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) as? (OfflineProgress) -> Void - perform?(`progress`) - } - - open func loadProgress(for blockID: String) -> OfflineProgress? { - addInvocation(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - var __value: OfflineProgress? = nil - do { - __value = try methodReturnValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))).casted() - } catch { - // do nothing - } - return __value - } - - open func loadAllOfflineProgress() -> [OfflineProgress] { - addInvocation(.m_loadAllOfflineProgress) - let perform = methodPerformValue(.m_loadAllOfflineProgress) as? () -> Void - perform?() - var __value: [OfflineProgress] - do { - __value = try methodReturnValue(.m_loadAllOfflineProgress).casted() - } catch { - onFatalFailure("Stub return value not specified for loadAllOfflineProgress(). Use given") - Failure("Stub return value not specified for loadAllOfflineProgress(). Use given") - } - return __value - } - - open func deleteProgress(for blockID: String) { - addInvocation(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - } - - open func deleteAllProgress() { - addInvocation(.m_deleteAllProgress) - let perform = methodPerformValue(.m_deleteAllProgress) as? () -> Void - perform?() - } - - open func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { - addInvocation(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) as? ([CourseBlock], DownloadQuality) -> Void - perform?(`blocks`, `downloadQuality`) - } - - open func updateTask(task: DownloadDataTask) { - addInvocation(.m_updateTask__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_updateTask__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - } - - open func downloadDataTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getDownloadDataTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasks) - let perform = methodPerformValue(.m_getDownloadDataTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasks(). Use given") - Failure("Stub return value not specified for getDownloadDataTasks(). Use given") - } - return __value - } - - open func getDownloadDataTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func deleteDownloadDataTasks(ids: [String]) { - addInvocation(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) - let perform = methodPerformValue(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) as? ([String]) -> Void - perform?(`ids`) - } - - - fileprivate enum MethodType { - case m_set__userId_userId(Parameter) - case m_getUserID - case m_publisher - case m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>) - case m_saveOfflineProgress__progress_progress(Parameter) - case m_loadProgress__for_blockID(Parameter) - case m_loadAllOfflineProgress - case m_deleteProgress__for_blockID(Parameter) - case m_deleteAllProgress - case m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>, Parameter) - case m_updateTask__task_task(Parameter) - case m_downloadDataTask__for_blockId(Parameter) - case m_getDownloadDataTasks - case m_getDownloadDataTasksForCourse__courseId(Parameter) - case m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_set__userId_userId(let lhsUserid), .m_set__userId_userId(let rhsUserid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUserid, rhs: rhsUserid, with: matcher), lhsUserid, rhsUserid, "userId")) - return Matcher.ComparisonResult(results) - - case (.m_getUserID, .m_getUserID): return .match - - case (.m_publisher, .m_publisher): return .match - - case (.m_addToDownloadQueue__tasks_tasks(let lhsTasks), .m_addToDownloadQueue__tasks_tasks(let rhsTasks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTasks, rhs: rhsTasks, with: matcher), lhsTasks, rhsTasks, "tasks")) - return Matcher.ComparisonResult(results) - - case (.m_saveOfflineProgress__progress_progress(let lhsProgress), .m_saveOfflineProgress__progress_progress(let rhsProgress)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsProgress, rhs: rhsProgress, with: matcher), lhsProgress, rhsProgress, "progress")) - return Matcher.ComparisonResult(results) - - case (.m_loadProgress__for_blockID(let lhsBlockid), .m_loadProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_loadAllOfflineProgress, .m_loadAllOfflineProgress): return .match - - case (.m_deleteProgress__for_blockID(let lhsBlockid), .m_deleteProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_deleteAllProgress, .m_deleteAllProgress): return .match - - case (.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let lhsBlocks, let lhsDownloadquality), .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let rhsBlocks, let rhsDownloadquality)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadquality, rhs: rhsDownloadquality, with: matcher), lhsDownloadquality, rhsDownloadquality, "downloadQuality")) - return Matcher.ComparisonResult(results) - - case (.m_updateTask__task_task(let lhsTask), .m_updateTask__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_downloadDataTask__for_blockId(let lhsBlockid), .m_downloadDataTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadDataTasks, .m_getDownloadDataTasks): return .match - - case (.m_getDownloadDataTasksForCourse__courseId(let lhsCourseid), .m_getDownloadDataTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_deleteDownloadDataTasks__ids_ids(let lhsIds), .m_deleteDownloadDataTasks__ids_ids(let rhsIds)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIds, rhs: rhsIds, with: matcher), lhsIds, rhsIds, "ids")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_set__userId_userId(p0): return p0.intValue - case .m_getUserID: return 0 - case .m_publisher: return 0 - case let .m_addToDownloadQueue__tasks_tasks(p0): return p0.intValue - case let .m_saveOfflineProgress__progress_progress(p0): return p0.intValue - case let .m_loadProgress__for_blockID(p0): return p0.intValue - case .m_loadAllOfflineProgress: return 0 - case let .m_deleteProgress__for_blockID(p0): return p0.intValue - case .m_deleteAllProgress: return 0 - case let .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(p0, p1): return p0.intValue + p1.intValue - case let .m_updateTask__task_task(p0): return p0.intValue - case let .m_downloadDataTask__for_blockId(p0): return p0.intValue - case .m_getDownloadDataTasks: return 0 - case let .m_getDownloadDataTasksForCourse__courseId(p0): return p0.intValue - case let .m_deleteDownloadDataTasks__ids_ids(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_set__userId_userId: return ".set(userId:)" - case .m_getUserID: return ".getUserID()" - case .m_publisher: return ".publisher()" - case .m_addToDownloadQueue__tasks_tasks: return ".addToDownloadQueue(tasks:)" - case .m_saveOfflineProgress__progress_progress: return ".saveOfflineProgress(progress:)" - case .m_loadProgress__for_blockID: return ".loadProgress(for:)" - case .m_loadAllOfflineProgress: return ".loadAllOfflineProgress()" - case .m_deleteProgress__for_blockID: return ".deleteProgress(for:)" - case .m_deleteAllProgress: return ".deleteAllProgress()" - case .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality: return ".addToDownloadQueue(blocks:downloadQuality:)" - case .m_updateTask__task_task: return ".updateTask(task:)" - case .m_downloadDataTask__for_blockId: return ".downloadDataTask(for:)" - case .m_getDownloadDataTasks: return ".getDownloadDataTasks()" - case .m_getDownloadDataTasksForCourse__courseId: return ".getDownloadDataTasksForCourse(_:)" - case .m_deleteDownloadDataTasks__ids_ids: return ".deleteDownloadDataTasks(ids:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getUserID(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @MainActor - public static func publisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_publisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadProgress(for blockID: Parameter, willReturn: OfflineProgress?...) -> MethodStub { - return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadAllOfflineProgress(willReturn: [OfflineProgress]...) -> MethodStub { - return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadDataTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getUserID(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func loadProgress(for blockID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [OfflineProgress?] = [] - let given: Given = { return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (OfflineProgress?).self) - willProduce(stubber) - return given - } - public static func loadAllOfflineProgress(willProduce: (Stubber<[OfflineProgress]>) -> Void) -> MethodStub { - let willReturn: [[OfflineProgress]] = [] - let given: Given = { return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([OfflineProgress]).self) - willProduce(stubber) - return given - } - public static func downloadDataTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - @MainActor - public static func publisher(willThrow: Error...) -> MethodStub { - return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) - } - @MainActor - public static func publisher(willProduce: (StubberThrows>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func set(userId: Parameter) -> Verify { return Verify(method: .m_set__userId_userId(`userId`))} - public static func getUserID() -> Verify { return Verify(method: .m_getUserID)} - @MainActor - public static func publisher() -> Verify { return Verify(method: .m_publisher)} - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>) -> Verify { return Verify(method: .m_addToDownloadQueue__tasks_tasks(`tasks`))} - public static func saveOfflineProgress(progress: Parameter) -> Verify { return Verify(method: .m_saveOfflineProgress__progress_progress(`progress`))} - public static func loadProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_loadProgress__for_blockID(`blockID`))} - public static func loadAllOfflineProgress() -> Verify { return Verify(method: .m_loadAllOfflineProgress)} - public static func deleteProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_deleteProgress__for_blockID(`blockID`))} - public static func deleteAllProgress() -> Verify { return Verify(method: .m_deleteAllProgress)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`))} - public static func updateTask(task: Parameter) -> Verify { return Verify(method: .m_updateTask__task_task(`task`))} - public static func downloadDataTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadDataTask__for_blockId(`blockId`))} - public static func getDownloadDataTasks() -> Verify { return Verify(method: .m_getDownloadDataTasks)} - public static func getDownloadDataTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`))} - public static func deleteDownloadDataTasks(ids: Parameter<[String]>) -> Verify { return Verify(method: .m_deleteDownloadDataTasks__ids_ids(`ids`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func set(userId: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_set__userId_userId(`userId`), performs: perform) - } - public static func getUserID(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getUserID, performs: perform) - } - @MainActor - public static func publisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_publisher, performs: perform) - } - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>, perform: @escaping ([DownloadDataTask]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__tasks_tasks(`tasks`), performs: perform) - } - public static func saveOfflineProgress(progress: Parameter, perform: @escaping (OfflineProgress) -> Void) -> Perform { - return Perform(method: .m_saveOfflineProgress__progress_progress(`progress`), performs: perform) - } - public static func loadProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_loadProgress__for_blockID(`blockID`), performs: perform) - } - public static func loadAllOfflineProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_loadAllOfflineProgress, performs: perform) - } - public static func deleteProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_deleteProgress__for_blockID(`blockID`), performs: perform) - } - public static func deleteAllProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAllProgress, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter, perform: @escaping ([CourseBlock], DownloadQuality) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`), performs: perform) - } - public static func updateTask(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_updateTask__task_task(`task`), performs: perform) - } - public static func downloadDataTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadDataTask__for_blockId(`blockId`), performs: perform) - } - public static func getDownloadDataTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasks, performs: perform) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func deleteDownloadDataTasks(ids: Parameter<[String]>, perform: @escaping ([String]) -> Void) -> Perform { - return Perform(method: .m_deleteDownloadDataTasks__ids_ids(`ids`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreStorage - -open class CoreStorageMock: CoreStorage, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var accessToken: String? { - get { invocations.append(.p_accessToken_get); return __p_accessToken ?? optionalGivenGetterValue(.p_accessToken_get, "CoreStorageMock - stub value for accessToken was not defined") } - set { invocations.append(.p_accessToken_set(.value(newValue))); __p_accessToken = newValue } - } - private var __p_accessToken: (String)? - - public var refreshToken: String? { - get { invocations.append(.p_refreshToken_get); return __p_refreshToken ?? optionalGivenGetterValue(.p_refreshToken_get, "CoreStorageMock - stub value for refreshToken was not defined") } - set { invocations.append(.p_refreshToken_set(.value(newValue))); __p_refreshToken = newValue } - } - private var __p_refreshToken: (String)? - - public var pushToken: String? { - get { invocations.append(.p_pushToken_get); return __p_pushToken ?? optionalGivenGetterValue(.p_pushToken_get, "CoreStorageMock - stub value for pushToken was not defined") } - set { invocations.append(.p_pushToken_set(.value(newValue))); __p_pushToken = newValue } - } - private var __p_pushToken: (String)? - - public var appleSignFullName: String? { - get { invocations.append(.p_appleSignFullName_get); return __p_appleSignFullName ?? optionalGivenGetterValue(.p_appleSignFullName_get, "CoreStorageMock - stub value for appleSignFullName was not defined") } - set { invocations.append(.p_appleSignFullName_set(.value(newValue))); __p_appleSignFullName = newValue } - } - private var __p_appleSignFullName: (String)? - - public var appleSignEmail: String? { - get { invocations.append(.p_appleSignEmail_get); return __p_appleSignEmail ?? optionalGivenGetterValue(.p_appleSignEmail_get, "CoreStorageMock - stub value for appleSignEmail was not defined") } - set { invocations.append(.p_appleSignEmail_set(.value(newValue))); __p_appleSignEmail = newValue } - } - private var __p_appleSignEmail: (String)? - - public var cookiesDate: Date? { - get { invocations.append(.p_cookiesDate_get); return __p_cookiesDate ?? optionalGivenGetterValue(.p_cookiesDate_get, "CoreStorageMock - stub value for cookiesDate was not defined") } - set { invocations.append(.p_cookiesDate_set(.value(newValue))); __p_cookiesDate = newValue } - } - private var __p_cookiesDate: (Date)? - - public var reviewLastShownVersion: String? { - get { invocations.append(.p_reviewLastShownVersion_get); return __p_reviewLastShownVersion ?? optionalGivenGetterValue(.p_reviewLastShownVersion_get, "CoreStorageMock - stub value for reviewLastShownVersion was not defined") } - set { invocations.append(.p_reviewLastShownVersion_set(.value(newValue))); __p_reviewLastShownVersion = newValue } - } - private var __p_reviewLastShownVersion: (String)? - - public var lastReviewDate: Date? { - get { invocations.append(.p_lastReviewDate_get); return __p_lastReviewDate ?? optionalGivenGetterValue(.p_lastReviewDate_get, "CoreStorageMock - stub value for lastReviewDate was not defined") } - set { invocations.append(.p_lastReviewDate_set(.value(newValue))); __p_lastReviewDate = newValue } - } - private var __p_lastReviewDate: (Date)? - - public var user: DataLayer.User? { - get { invocations.append(.p_user_get); return __p_user ?? optionalGivenGetterValue(.p_user_get, "CoreStorageMock - stub value for user was not defined") } - set { invocations.append(.p_user_set(.value(newValue))); __p_user = newValue } - } - private var __p_user: (DataLayer.User)? - - public var userSettings: UserSettings? { - get { invocations.append(.p_userSettings_get); return __p_userSettings ?? optionalGivenGetterValue(.p_userSettings_get, "CoreStorageMock - stub value for userSettings was not defined") } - set { invocations.append(.p_userSettings_set(.value(newValue))); __p_userSettings = newValue } - } - private var __p_userSettings: (UserSettings)? - - public var resetAppSupportDirectoryUserData: Bool? { - get { invocations.append(.p_resetAppSupportDirectoryUserData_get); return __p_resetAppSupportDirectoryUserData ?? optionalGivenGetterValue(.p_resetAppSupportDirectoryUserData_get, "CoreStorageMock - stub value for resetAppSupportDirectoryUserData was not defined") } - set { invocations.append(.p_resetAppSupportDirectoryUserData_set(.value(newValue))); __p_resetAppSupportDirectoryUserData = newValue } - } - private var __p_resetAppSupportDirectoryUserData: (Bool)? - - public var useRelativeDates: Bool { - get { invocations.append(.p_useRelativeDates_get); return __p_useRelativeDates ?? givenGetterValue(.p_useRelativeDates_get, "CoreStorageMock - stub value for useRelativeDates was not defined") } - set { invocations.append(.p_useRelativeDates_set(.value(newValue))); __p_useRelativeDates = newValue } - } - private var __p_useRelativeDates: (Bool)? - - public var lastUsedSocialAuth: String? { - get { invocations.append(.p_lastUsedSocialAuth_get); return __p_lastUsedSocialAuth ?? optionalGivenGetterValue(.p_lastUsedSocialAuth_get, "CoreStorageMock - stub value for lastUsedSocialAuth was not defined") } - set { invocations.append(.p_lastUsedSocialAuth_set(.value(newValue))); __p_lastUsedSocialAuth = newValue } - } - private var __p_lastUsedSocialAuth: (String)? - - public var latestAvailableAppVersion: String? { - get { invocations.append(.p_latestAvailableAppVersion_get); return __p_latestAvailableAppVersion ?? optionalGivenGetterValue(.p_latestAvailableAppVersion_get, "CoreStorageMock - stub value for latestAvailableAppVersion was not defined") } - set { invocations.append(.p_latestAvailableAppVersion_set(.value(newValue))); __p_latestAvailableAppVersion = newValue } - } - private var __p_latestAvailableAppVersion: (String)? - - public var updateAppRequired: Bool { - get { invocations.append(.p_updateAppRequired_get); return __p_updateAppRequired ?? givenGetterValue(.p_updateAppRequired_get, "CoreStorageMock - stub value for updateAppRequired was not defined") } - set { invocations.append(.p_updateAppRequired_set(.value(newValue))); __p_updateAppRequired = newValue } - } - private var __p_updateAppRequired: (Bool)? - - - - - - open func clear() { - addInvocation(.m_clear) - let perform = methodPerformValue(.m_clear) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_clear - case p_accessToken_get - case p_accessToken_set(Parameter) - case p_refreshToken_get - case p_refreshToken_set(Parameter) - case p_pushToken_get - case p_pushToken_set(Parameter) - case p_appleSignFullName_get - case p_appleSignFullName_set(Parameter) - case p_appleSignEmail_get - case p_appleSignEmail_set(Parameter) - case p_cookiesDate_get - case p_cookiesDate_set(Parameter) - case p_reviewLastShownVersion_get - case p_reviewLastShownVersion_set(Parameter) - case p_lastReviewDate_get - case p_lastReviewDate_set(Parameter) - case p_user_get - case p_user_set(Parameter) - case p_userSettings_get - case p_userSettings_set(Parameter) - case p_resetAppSupportDirectoryUserData_get - case p_resetAppSupportDirectoryUserData_set(Parameter) - case p_useRelativeDates_get - case p_useRelativeDates_set(Parameter) - case p_lastUsedSocialAuth_get - case p_lastUsedSocialAuth_set(Parameter) - case p_latestAvailableAppVersion_get - case p_latestAvailableAppVersion_set(Parameter) - case p_updateAppRequired_get - case p_updateAppRequired_set(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_clear, .m_clear): return .match - case (.p_accessToken_get,.p_accessToken_get): return Matcher.ComparisonResult.match - case (.p_accessToken_set(let left),.p_accessToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_refreshToken_get,.p_refreshToken_get): return Matcher.ComparisonResult.match - case (.p_refreshToken_set(let left),.p_refreshToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_pushToken_get,.p_pushToken_get): return Matcher.ComparisonResult.match - case (.p_pushToken_set(let left),.p_pushToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignFullName_get,.p_appleSignFullName_get): return Matcher.ComparisonResult.match - case (.p_appleSignFullName_set(let left),.p_appleSignFullName_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignEmail_get,.p_appleSignEmail_get): return Matcher.ComparisonResult.match - case (.p_appleSignEmail_set(let left),.p_appleSignEmail_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_cookiesDate_get,.p_cookiesDate_get): return Matcher.ComparisonResult.match - case (.p_cookiesDate_set(let left),.p_cookiesDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_reviewLastShownVersion_get,.p_reviewLastShownVersion_get): return Matcher.ComparisonResult.match - case (.p_reviewLastShownVersion_set(let left),.p_reviewLastShownVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastReviewDate_get,.p_lastReviewDate_get): return Matcher.ComparisonResult.match - case (.p_lastReviewDate_set(let left),.p_lastReviewDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_user_get,.p_user_get): return Matcher.ComparisonResult.match - case (.p_user_set(let left),.p_user_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_userSettings_get,.p_userSettings_get): return Matcher.ComparisonResult.match - case (.p_userSettings_set(let left),.p_userSettings_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_resetAppSupportDirectoryUserData_get,.p_resetAppSupportDirectoryUserData_get): return Matcher.ComparisonResult.match - case (.p_resetAppSupportDirectoryUserData_set(let left),.p_resetAppSupportDirectoryUserData_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_useRelativeDates_get,.p_useRelativeDates_get): return Matcher.ComparisonResult.match - case (.p_useRelativeDates_set(let left),.p_useRelativeDates_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastUsedSocialAuth_get,.p_lastUsedSocialAuth_get): return Matcher.ComparisonResult.match - case (.p_lastUsedSocialAuth_set(let left),.p_lastUsedSocialAuth_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_latestAvailableAppVersion_get,.p_latestAvailableAppVersion_get): return Matcher.ComparisonResult.match - case (.p_latestAvailableAppVersion_set(let left),.p_latestAvailableAppVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_updateAppRequired_get,.p_updateAppRequired_get): return Matcher.ComparisonResult.match - case (.p_updateAppRequired_set(let left),.p_updateAppRequired_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_clear: return 0 - case .p_accessToken_get: return 0 - case .p_accessToken_set(let newValue): return newValue.intValue - case .p_refreshToken_get: return 0 - case .p_refreshToken_set(let newValue): return newValue.intValue - case .p_pushToken_get: return 0 - case .p_pushToken_set(let newValue): return newValue.intValue - case .p_appleSignFullName_get: return 0 - case .p_appleSignFullName_set(let newValue): return newValue.intValue - case .p_appleSignEmail_get: return 0 - case .p_appleSignEmail_set(let newValue): return newValue.intValue - case .p_cookiesDate_get: return 0 - case .p_cookiesDate_set(let newValue): return newValue.intValue - case .p_reviewLastShownVersion_get: return 0 - case .p_reviewLastShownVersion_set(let newValue): return newValue.intValue - case .p_lastReviewDate_get: return 0 - case .p_lastReviewDate_set(let newValue): return newValue.intValue - case .p_user_get: return 0 - case .p_user_set(let newValue): return newValue.intValue - case .p_userSettings_get: return 0 - case .p_userSettings_set(let newValue): return newValue.intValue - case .p_resetAppSupportDirectoryUserData_get: return 0 - case .p_resetAppSupportDirectoryUserData_set(let newValue): return newValue.intValue - case .p_useRelativeDates_get: return 0 - case .p_useRelativeDates_set(let newValue): return newValue.intValue - case .p_lastUsedSocialAuth_get: return 0 - case .p_lastUsedSocialAuth_set(let newValue): return newValue.intValue - case .p_latestAvailableAppVersion_get: return 0 - case .p_latestAvailableAppVersion_set(let newValue): return newValue.intValue - case .p_updateAppRequired_get: return 0 - case .p_updateAppRequired_set(let newValue): return newValue.intValue - } - } - func assertionName() -> String { - switch self { - case .m_clear: return ".clear()" - case .p_accessToken_get: return "[get] .accessToken" - case .p_accessToken_set: return "[set] .accessToken" - case .p_refreshToken_get: return "[get] .refreshToken" - case .p_refreshToken_set: return "[set] .refreshToken" - case .p_pushToken_get: return "[get] .pushToken" - case .p_pushToken_set: return "[set] .pushToken" - case .p_appleSignFullName_get: return "[get] .appleSignFullName" - case .p_appleSignFullName_set: return "[set] .appleSignFullName" - case .p_appleSignEmail_get: return "[get] .appleSignEmail" - case .p_appleSignEmail_set: return "[set] .appleSignEmail" - case .p_cookiesDate_get: return "[get] .cookiesDate" - case .p_cookiesDate_set: return "[set] .cookiesDate" - case .p_reviewLastShownVersion_get: return "[get] .reviewLastShownVersion" - case .p_reviewLastShownVersion_set: return "[set] .reviewLastShownVersion" - case .p_lastReviewDate_get: return "[get] .lastReviewDate" - case .p_lastReviewDate_set: return "[set] .lastReviewDate" - case .p_user_get: return "[get] .user" - case .p_user_set: return "[set] .user" - case .p_userSettings_get: return "[get] .userSettings" - case .p_userSettings_set: return "[set] .userSettings" - case .p_resetAppSupportDirectoryUserData_get: return "[get] .resetAppSupportDirectoryUserData" - case .p_resetAppSupportDirectoryUserData_set: return "[set] .resetAppSupportDirectoryUserData" - case .p_useRelativeDates_get: return "[get] .useRelativeDates" - case .p_useRelativeDates_set: return "[set] .useRelativeDates" - case .p_lastUsedSocialAuth_get: return "[get] .lastUsedSocialAuth" - case .p_lastUsedSocialAuth_set: return "[set] .lastUsedSocialAuth" - case .p_latestAvailableAppVersion_get: return "[get] .latestAvailableAppVersion" - case .p_latestAvailableAppVersion_set: return "[set] .latestAvailableAppVersion" - case .p_updateAppRequired_get: return "[get] .updateAppRequired" - case .p_updateAppRequired_set: return "[set] .updateAppRequired" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func accessToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_accessToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func refreshToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_refreshToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func pushToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_pushToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignFullName(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignFullName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignEmail(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func cookiesDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_cookiesDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func reviewLastShownVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_reviewLastShownVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastReviewDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_lastReviewDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func user(getter defaultValue: DataLayer.User?...) -> PropertyStub { - return Given(method: .p_user_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func userSettings(getter defaultValue: UserSettings?...) -> PropertyStub { - return Given(method: .p_userSettings_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func resetAppSupportDirectoryUserData(getter defaultValue: Bool?...) -> PropertyStub { - return Given(method: .p_resetAppSupportDirectoryUserData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func useRelativeDates(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_useRelativeDates_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastUsedSocialAuth(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_lastUsedSocialAuth_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func latestAvailableAppVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_latestAvailableAppVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func updateAppRequired(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_updateAppRequired_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func clear() -> Verify { return Verify(method: .m_clear)} - public static var accessToken: Verify { return Verify(method: .p_accessToken_get) } - public static func accessToken(set newValue: Parameter) -> Verify { return Verify(method: .p_accessToken_set(newValue)) } - public static var refreshToken: Verify { return Verify(method: .p_refreshToken_get) } - public static func refreshToken(set newValue: Parameter) -> Verify { return Verify(method: .p_refreshToken_set(newValue)) } - public static var pushToken: Verify { return Verify(method: .p_pushToken_get) } - public static func pushToken(set newValue: Parameter) -> Verify { return Verify(method: .p_pushToken_set(newValue)) } - public static var appleSignFullName: Verify { return Verify(method: .p_appleSignFullName_get) } - public static func appleSignFullName(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignFullName_set(newValue)) } - public static var appleSignEmail: Verify { return Verify(method: .p_appleSignEmail_get) } - public static func appleSignEmail(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignEmail_set(newValue)) } - public static var cookiesDate: Verify { return Verify(method: .p_cookiesDate_get) } - public static func cookiesDate(set newValue: Parameter) -> Verify { return Verify(method: .p_cookiesDate_set(newValue)) } - public static var reviewLastShownVersion: Verify { return Verify(method: .p_reviewLastShownVersion_get) } - public static func reviewLastShownVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_reviewLastShownVersion_set(newValue)) } - public static var lastReviewDate: Verify { return Verify(method: .p_lastReviewDate_get) } - public static func lastReviewDate(set newValue: Parameter) -> Verify { return Verify(method: .p_lastReviewDate_set(newValue)) } - public static var user: Verify { return Verify(method: .p_user_get) } - public static func user(set newValue: Parameter) -> Verify { return Verify(method: .p_user_set(newValue)) } - public static var userSettings: Verify { return Verify(method: .p_userSettings_get) } - public static func userSettings(set newValue: Parameter) -> Verify { return Verify(method: .p_userSettings_set(newValue)) } - public static var resetAppSupportDirectoryUserData: Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_get) } - public static func resetAppSupportDirectoryUserData(set newValue: Parameter) -> Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_set(newValue)) } - public static var useRelativeDates: Verify { return Verify(method: .p_useRelativeDates_get) } - public static func useRelativeDates(set newValue: Parameter) -> Verify { return Verify(method: .p_useRelativeDates_set(newValue)) } - public static var lastUsedSocialAuth: Verify { return Verify(method: .p_lastUsedSocialAuth_get) } - public static func lastUsedSocialAuth(set newValue: Parameter) -> Verify { return Verify(method: .p_lastUsedSocialAuth_set(newValue)) } - public static var latestAvailableAppVersion: Verify { return Verify(method: .p_latestAvailableAppVersion_get) } - public static func latestAvailableAppVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_latestAvailableAppVersion_set(newValue)) } - public static var updateAppRequired: Verify { return Verify(method: .p_updateAppRequired_get) } - public static func updateAppRequired(set newValue: Parameter) -> Verify { return Verify(method: .p_updateAppRequired_set(newValue)) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func clear(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_clear, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CourseStructureManagerProtocol - -open class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getLoadedCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func shiftDueDates(courseID: String) throws { - addInvocation(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - do { - _ = try methodReturnValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - - fileprivate enum MethodType { - case m_getCourseBlocks__courseID_courseID(Parameter) - case m_getLoadedCourseBlocks__courseID_courseID(Parameter) - case m_shiftDueDates__courseID_courseID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseBlocks__courseID_courseID(let lhsCourseid), .m_getCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getLoadedCourseBlocks__courseID_courseID(let lhsCourseid), .m_getLoadedCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_shiftDueDates__courseID_courseID(let lhsCourseid), .m_shiftDueDates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_getLoadedCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_shiftDueDates__courseID_courseID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getCourseBlocks__courseID_courseID: return ".getCourseBlocks(courseID:)" - case .m_getLoadedCourseBlocks__courseID_courseID: return ".getLoadedCourseBlocks(courseID:)" - case .m_shiftDueDates__courseID_courseID: return ".shiftDueDates(courseID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getLoadedCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func shiftDueDates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func shiftDueDates(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseBlocks__courseID_courseID(`courseID`))} - public static func getLoadedCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`))} - public static func shiftDueDates(courseID: Parameter) -> Verify { return Verify(method: .m_shiftDueDates__courseID_courseID(`courseID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func getLoadedCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func shiftDueDates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_shiftDueDates__courseID_courseID(`courseID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DiscussionAnalytics - -open class DiscussionAnalyticsMock: DiscussionAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func discussionAllPostsClicked(courseId: String, courseName: String) { - addInvocation(.m_discussionAllPostsClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_discussionAllPostsClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func discussionFollowingClicked(courseId: String, courseName: String) { - addInvocation(.m_discussionFollowingClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_discussionFollowingClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func discussionTopicClicked(courseId: String, courseName: String, topicId: String, topicName: String) { - addInvocation(.m_discussionTopicClicked__courseId_courseIdcourseName_courseNametopicId_topicIdtopicName_topicName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`topicId`), Parameter.value(`topicName`))) - let perform = methodPerformValue(.m_discussionTopicClicked__courseId_courseIdcourseName_courseNametopicId_topicIdtopicName_topicName(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`topicId`), Parameter.value(`topicName`))) as? (String, String, String, String) -> Void - perform?(`courseId`, `courseName`, `topicId`, `topicName`) - } - - open func discussionCreateNewPost(courseID: String, topicID: String, postType: String, followPost: Bool, author: String) { - addInvocation(.m_discussionCreateNewPost__courseID_courseIDtopicID_topicIDpostType_postTypefollowPost_followPostauthor_author(Parameter.value(`courseID`), Parameter.value(`topicID`), Parameter.value(`postType`), Parameter.value(`followPost`), Parameter.value(`author`))) - let perform = methodPerformValue(.m_discussionCreateNewPost__courseID_courseIDtopicID_topicIDpostType_postTypefollowPost_followPostauthor_author(Parameter.value(`courseID`), Parameter.value(`topicID`), Parameter.value(`postType`), Parameter.value(`followPost`), Parameter.value(`author`))) as? (String, String, String, Bool, String) -> Void - perform?(`courseID`, `topicID`, `postType`, `followPost`, `author`) - } - - open func discussionResponseAdded(courseID: String, threadID: String, responseID: String, author: String) { - addInvocation(.m_discussionResponseAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDauthor_author(Parameter.value(`courseID`), Parameter.value(`threadID`), Parameter.value(`responseID`), Parameter.value(`author`))) - let perform = methodPerformValue(.m_discussionResponseAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDauthor_author(Parameter.value(`courseID`), Parameter.value(`threadID`), Parameter.value(`responseID`), Parameter.value(`author`))) as? (String, String, String, String) -> Void - perform?(`courseID`, `threadID`, `responseID`, `author`) - } - - open func discussionCommentAdded(courseID: String, threadID: String, responseID: String, commentID: String, author: String) { - addInvocation(.m_discussionCommentAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_author(Parameter.value(`courseID`), Parameter.value(`threadID`), Parameter.value(`responseID`), Parameter.value(`commentID`), Parameter.value(`author`))) - let perform = methodPerformValue(.m_discussionCommentAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_author(Parameter.value(`courseID`), Parameter.value(`threadID`), Parameter.value(`responseID`), Parameter.value(`commentID`), Parameter.value(`author`))) as? (String, String, String, String, String) -> Void - perform?(`courseID`, `threadID`, `responseID`, `commentID`, `author`) - } - - open func discussionFollowToggle(courseID: String, threadID: String, author: String, follow: Bool) { - addInvocation(.m_discussionFollowToggle__courseID_courseIDthreadID_threadIDauthor_authorfollow_follow(Parameter.value(`courseID`), Parameter.value(`threadID`), Parameter.value(`author`), Parameter.value(`follow`))) - let perform = methodPerformValue(.m_discussionFollowToggle__courseID_courseIDthreadID_threadIDauthor_authorfollow_follow(Parameter.value(`courseID`), Parameter.value(`threadID`), Parameter.value(`author`), Parameter.value(`follow`))) as? (String, String, String, Bool) -> Void - perform?(`courseID`, `threadID`, `author`, `follow`) - } - - open func discussionLikeToggle(courseID: String, threadID: String, responseID: String?, commentID: String?, author: String, discussionType: String, like: Bool) { - addInvocation(.m_discussionLikeToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypelike_like(Parameter.value(`courseID`), Parameter.value(`threadID`), Parameter.value(`responseID`), Parameter.value(`commentID`), Parameter.value(`author`), Parameter.value(`discussionType`), Parameter.value(`like`))) - let perform = methodPerformValue(.m_discussionLikeToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypelike_like(Parameter.value(`courseID`), Parameter.value(`threadID`), Parameter.value(`responseID`), Parameter.value(`commentID`), Parameter.value(`author`), Parameter.value(`discussionType`), Parameter.value(`like`))) as? (String, String, String?, String?, String, String, Bool) -> Void - perform?(`courseID`, `threadID`, `responseID`, `commentID`, `author`, `discussionType`, `like`) - } - - open func discussionReportToggle(courseID: String, threadID: String, responseID: String?, commentID: String?, author: String, discussionType: String, report: Bool) { - addInvocation(.m_discussionReportToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypereport_report(Parameter.value(`courseID`), Parameter.value(`threadID`), Parameter.value(`responseID`), Parameter.value(`commentID`), Parameter.value(`author`), Parameter.value(`discussionType`), Parameter.value(`report`))) - let perform = methodPerformValue(.m_discussionReportToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypereport_report(Parameter.value(`courseID`), Parameter.value(`threadID`), Parameter.value(`responseID`), Parameter.value(`commentID`), Parameter.value(`author`), Parameter.value(`discussionType`), Parameter.value(`report`))) as? (String, String, String?, String?, String, String, Bool) -> Void - perform?(`courseID`, `threadID`, `responseID`, `commentID`, `author`, `discussionType`, `report`) - } - - - fileprivate enum MethodType { - case m_discussionAllPostsClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_discussionFollowingClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_discussionTopicClicked__courseId_courseIdcourseName_courseNametopicId_topicIdtopicName_topicName(Parameter, Parameter, Parameter, Parameter) - case m_discussionCreateNewPost__courseID_courseIDtopicID_topicIDpostType_postTypefollowPost_followPostauthor_author(Parameter, Parameter, Parameter, Parameter, Parameter) - case m_discussionResponseAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDauthor_author(Parameter, Parameter, Parameter, Parameter) - case m_discussionCommentAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_author(Parameter, Parameter, Parameter, Parameter, Parameter) - case m_discussionFollowToggle__courseID_courseIDthreadID_threadIDauthor_authorfollow_follow(Parameter, Parameter, Parameter, Parameter) - case m_discussionLikeToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypelike_like(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter) - case m_discussionReportToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypereport_report(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_discussionAllPostsClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_discussionAllPostsClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_discussionFollowingClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_discussionFollowingClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_discussionTopicClicked__courseId_courseIdcourseName_courseNametopicId_topicIdtopicName_topicName(let lhsCourseid, let lhsCoursename, let lhsTopicid, let lhsTopicname), .m_discussionTopicClicked__courseId_courseIdcourseName_courseNametopicId_topicIdtopicName_topicName(let rhsCourseid, let rhsCoursename, let rhsTopicid, let rhsTopicname)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTopicid, rhs: rhsTopicid, with: matcher), lhsTopicid, rhsTopicid, "topicId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTopicname, rhs: rhsTopicname, with: matcher), lhsTopicname, rhsTopicname, "topicName")) - return Matcher.ComparisonResult(results) - - case (.m_discussionCreateNewPost__courseID_courseIDtopicID_topicIDpostType_postTypefollowPost_followPostauthor_author(let lhsCourseid, let lhsTopicid, let lhsPosttype, let lhsFollowpost, let lhsAuthor), .m_discussionCreateNewPost__courseID_courseIDtopicID_topicIDpostType_postTypefollowPost_followPostauthor_author(let rhsCourseid, let rhsTopicid, let rhsPosttype, let rhsFollowpost, let rhsAuthor)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTopicid, rhs: rhsTopicid, with: matcher), lhsTopicid, rhsTopicid, "topicID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPosttype, rhs: rhsPosttype, with: matcher), lhsPosttype, rhsPosttype, "postType")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFollowpost, rhs: rhsFollowpost, with: matcher), lhsFollowpost, rhsFollowpost, "followPost")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAuthor, rhs: rhsAuthor, with: matcher), lhsAuthor, rhsAuthor, "author")) - return Matcher.ComparisonResult(results) - - case (.m_discussionResponseAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDauthor_author(let lhsCourseid, let lhsThreadid, let lhsResponseid, let lhsAuthor), .m_discussionResponseAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDauthor_author(let rhsCourseid, let rhsThreadid, let rhsResponseid, let rhsAuthor)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsResponseid, rhs: rhsResponseid, with: matcher), lhsResponseid, rhsResponseid, "responseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAuthor, rhs: rhsAuthor, with: matcher), lhsAuthor, rhsAuthor, "author")) - return Matcher.ComparisonResult(results) - - case (.m_discussionCommentAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_author(let lhsCourseid, let lhsThreadid, let lhsResponseid, let lhsCommentid, let lhsAuthor), .m_discussionCommentAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_author(let rhsCourseid, let rhsThreadid, let rhsResponseid, let rhsCommentid, let rhsAuthor)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsResponseid, rhs: rhsResponseid, with: matcher), lhsResponseid, rhsResponseid, "responseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCommentid, rhs: rhsCommentid, with: matcher), lhsCommentid, rhsCommentid, "commentID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAuthor, rhs: rhsAuthor, with: matcher), lhsAuthor, rhsAuthor, "author")) - return Matcher.ComparisonResult(results) - - case (.m_discussionFollowToggle__courseID_courseIDthreadID_threadIDauthor_authorfollow_follow(let lhsCourseid, let lhsThreadid, let lhsAuthor, let lhsFollow), .m_discussionFollowToggle__courseID_courseIDthreadID_threadIDauthor_authorfollow_follow(let rhsCourseid, let rhsThreadid, let rhsAuthor, let rhsFollow)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAuthor, rhs: rhsAuthor, with: matcher), lhsAuthor, rhsAuthor, "author")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFollow, rhs: rhsFollow, with: matcher), lhsFollow, rhsFollow, "follow")) - return Matcher.ComparisonResult(results) - - case (.m_discussionLikeToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypelike_like(let lhsCourseid, let lhsThreadid, let lhsResponseid, let lhsCommentid, let lhsAuthor, let lhsDiscussiontype, let lhsLike), .m_discussionLikeToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypelike_like(let rhsCourseid, let rhsThreadid, let rhsResponseid, let rhsCommentid, let rhsAuthor, let rhsDiscussiontype, let rhsLike)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsResponseid, rhs: rhsResponseid, with: matcher), lhsResponseid, rhsResponseid, "responseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCommentid, rhs: rhsCommentid, with: matcher), lhsCommentid, rhsCommentid, "commentID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAuthor, rhs: rhsAuthor, with: matcher), lhsAuthor, rhsAuthor, "author")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDiscussiontype, rhs: rhsDiscussiontype, with: matcher), lhsDiscussiontype, rhsDiscussiontype, "discussionType")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsLike, rhs: rhsLike, with: matcher), lhsLike, rhsLike, "like")) - return Matcher.ComparisonResult(results) - - case (.m_discussionReportToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypereport_report(let lhsCourseid, let lhsThreadid, let lhsResponseid, let lhsCommentid, let lhsAuthor, let lhsDiscussiontype, let lhsReport), .m_discussionReportToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypereport_report(let rhsCourseid, let rhsThreadid, let rhsResponseid, let rhsCommentid, let rhsAuthor, let rhsDiscussiontype, let rhsReport)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsResponseid, rhs: rhsResponseid, with: matcher), lhsResponseid, rhsResponseid, "responseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCommentid, rhs: rhsCommentid, with: matcher), lhsCommentid, rhsCommentid, "commentID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAuthor, rhs: rhsAuthor, with: matcher), lhsAuthor, rhsAuthor, "author")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDiscussiontype, rhs: rhsDiscussiontype, with: matcher), lhsDiscussiontype, rhsDiscussiontype, "discussionType")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsReport, rhs: rhsReport, with: matcher), lhsReport, rhsReport, "report")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_discussionAllPostsClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_discussionFollowingClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_discussionTopicClicked__courseId_courseIdcourseName_courseNametopicId_topicIdtopicName_topicName(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_discussionCreateNewPost__courseID_courseIDtopicID_topicIDpostType_postTypefollowPost_followPostauthor_author(p0, p1, p2, p3, p4): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue - case let .m_discussionResponseAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDauthor_author(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_discussionCommentAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_author(p0, p1, p2, p3, p4): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue - case let .m_discussionFollowToggle__courseID_courseIDthreadID_threadIDauthor_authorfollow_follow(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_discussionLikeToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypelike_like(p0, p1, p2, p3, p4, p5, p6): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue - case let .m_discussionReportToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypereport_report(p0, p1, p2, p3, p4, p5, p6): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue - } - } - func assertionName() -> String { - switch self { - case .m_discussionAllPostsClicked__courseId_courseIdcourseName_courseName: return ".discussionAllPostsClicked(courseId:courseName:)" - case .m_discussionFollowingClicked__courseId_courseIdcourseName_courseName: return ".discussionFollowingClicked(courseId:courseName:)" - case .m_discussionTopicClicked__courseId_courseIdcourseName_courseNametopicId_topicIdtopicName_topicName: return ".discussionTopicClicked(courseId:courseName:topicId:topicName:)" - case .m_discussionCreateNewPost__courseID_courseIDtopicID_topicIDpostType_postTypefollowPost_followPostauthor_author: return ".discussionCreateNewPost(courseID:topicID:postType:followPost:author:)" - case .m_discussionResponseAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDauthor_author: return ".discussionResponseAdded(courseID:threadID:responseID:author:)" - case .m_discussionCommentAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_author: return ".discussionCommentAdded(courseID:threadID:responseID:commentID:author:)" - case .m_discussionFollowToggle__courseID_courseIDthreadID_threadIDauthor_authorfollow_follow: return ".discussionFollowToggle(courseID:threadID:author:follow:)" - case .m_discussionLikeToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypelike_like: return ".discussionLikeToggle(courseID:threadID:responseID:commentID:author:discussionType:like:)" - case .m_discussionReportToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypereport_report: return ".discussionReportToggle(courseID:threadID:responseID:commentID:author:discussionType:report:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func discussionAllPostsClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_discussionAllPostsClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func discussionFollowingClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_discussionFollowingClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func discussionTopicClicked(courseId: Parameter, courseName: Parameter, topicId: Parameter, topicName: Parameter) -> Verify { return Verify(method: .m_discussionTopicClicked__courseId_courseIdcourseName_courseNametopicId_topicIdtopicName_topicName(`courseId`, `courseName`, `topicId`, `topicName`))} - public static func discussionCreateNewPost(courseID: Parameter, topicID: Parameter, postType: Parameter, followPost: Parameter, author: Parameter) -> Verify { return Verify(method: .m_discussionCreateNewPost__courseID_courseIDtopicID_topicIDpostType_postTypefollowPost_followPostauthor_author(`courseID`, `topicID`, `postType`, `followPost`, `author`))} - public static func discussionResponseAdded(courseID: Parameter, threadID: Parameter, responseID: Parameter, author: Parameter) -> Verify { return Verify(method: .m_discussionResponseAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDauthor_author(`courseID`, `threadID`, `responseID`, `author`))} - public static func discussionCommentAdded(courseID: Parameter, threadID: Parameter, responseID: Parameter, commentID: Parameter, author: Parameter) -> Verify { return Verify(method: .m_discussionCommentAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_author(`courseID`, `threadID`, `responseID`, `commentID`, `author`))} - public static func discussionFollowToggle(courseID: Parameter, threadID: Parameter, author: Parameter, follow: Parameter) -> Verify { return Verify(method: .m_discussionFollowToggle__courseID_courseIDthreadID_threadIDauthor_authorfollow_follow(`courseID`, `threadID`, `author`, `follow`))} - public static func discussionLikeToggle(courseID: Parameter, threadID: Parameter, responseID: Parameter, commentID: Parameter, author: Parameter, discussionType: Parameter, like: Parameter) -> Verify { return Verify(method: .m_discussionLikeToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypelike_like(`courseID`, `threadID`, `responseID`, `commentID`, `author`, `discussionType`, `like`))} - public static func discussionReportToggle(courseID: Parameter, threadID: Parameter, responseID: Parameter, commentID: Parameter, author: Parameter, discussionType: Parameter, report: Parameter) -> Verify { return Verify(method: .m_discussionReportToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypereport_report(`courseID`, `threadID`, `responseID`, `commentID`, `author`, `discussionType`, `report`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func discussionAllPostsClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_discussionAllPostsClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func discussionFollowingClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_discussionFollowingClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func discussionTopicClicked(courseId: Parameter, courseName: Parameter, topicId: Parameter, topicName: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_discussionTopicClicked__courseId_courseIdcourseName_courseNametopicId_topicIdtopicName_topicName(`courseId`, `courseName`, `topicId`, `topicName`), performs: perform) - } - public static func discussionCreateNewPost(courseID: Parameter, topicID: Parameter, postType: Parameter, followPost: Parameter, author: Parameter, perform: @escaping (String, String, String, Bool, String) -> Void) -> Perform { - return Perform(method: .m_discussionCreateNewPost__courseID_courseIDtopicID_topicIDpostType_postTypefollowPost_followPostauthor_author(`courseID`, `topicID`, `postType`, `followPost`, `author`), performs: perform) - } - public static func discussionResponseAdded(courseID: Parameter, threadID: Parameter, responseID: Parameter, author: Parameter, perform: @escaping (String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_discussionResponseAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDauthor_author(`courseID`, `threadID`, `responseID`, `author`), performs: perform) - } - public static func discussionCommentAdded(courseID: Parameter, threadID: Parameter, responseID: Parameter, commentID: Parameter, author: Parameter, perform: @escaping (String, String, String, String, String) -> Void) -> Perform { - return Perform(method: .m_discussionCommentAdded__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_author(`courseID`, `threadID`, `responseID`, `commentID`, `author`), performs: perform) - } - public static func discussionFollowToggle(courseID: Parameter, threadID: Parameter, author: Parameter, follow: Parameter, perform: @escaping (String, String, String, Bool) -> Void) -> Perform { - return Perform(method: .m_discussionFollowToggle__courseID_courseIDthreadID_threadIDauthor_authorfollow_follow(`courseID`, `threadID`, `author`, `follow`), performs: perform) - } - public static func discussionLikeToggle(courseID: Parameter, threadID: Parameter, responseID: Parameter, commentID: Parameter, author: Parameter, discussionType: Parameter, like: Parameter, perform: @escaping (String, String, String?, String?, String, String, Bool) -> Void) -> Perform { - return Perform(method: .m_discussionLikeToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypelike_like(`courseID`, `threadID`, `responseID`, `commentID`, `author`, `discussionType`, `like`), performs: perform) - } - public static func discussionReportToggle(courseID: Parameter, threadID: Parameter, responseID: Parameter, commentID: Parameter, author: Parameter, discussionType: Parameter, report: Parameter, perform: @escaping (String, String, String?, String?, String, String, Bool) -> Void) -> Perform { - return Perform(method: .m_discussionReportToggle__courseID_courseIDthreadID_threadIDresponseID_responseIDcommentID_commentIDauthor_authordiscussionType_discussionTypereport_report(`courseID`, `threadID`, `responseID`, `commentID`, `author`, `discussionType`, `report`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DiscussionInteractorProtocol - -open class DiscussionInteractorProtocolMock: DiscussionInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseDiscussionInfo(courseID: String) throws -> DiscussionInfo { - addInvocation(.m_getCourseDiscussionInfo__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseDiscussionInfo__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: DiscussionInfo - do { - __value = try methodReturnValue(.m_getCourseDiscussionInfo__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseDiscussionInfo(courseID: String). Use given") - Failure("Stub return value not specified for getCourseDiscussionInfo(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getThreadsList(courseID: String, type: ThreadType, sort: SortType, filter: ThreadsFilter, page: Int) throws -> ThreadLists { - addInvocation(.m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page(Parameter.value(`courseID`), Parameter.value(`type`), Parameter.value(`sort`), Parameter.value(`filter`), Parameter.value(`page`))) - let perform = methodPerformValue(.m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page(Parameter.value(`courseID`), Parameter.value(`type`), Parameter.value(`sort`), Parameter.value(`filter`), Parameter.value(`page`))) as? (String, ThreadType, SortType, ThreadsFilter, Int) -> Void - perform?(`courseID`, `type`, `sort`, `filter`, `page`) - var __value: ThreadLists - do { - __value = try methodReturnValue(.m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page(Parameter.value(`courseID`), Parameter.value(`type`), Parameter.value(`sort`), Parameter.value(`filter`), Parameter.value(`page`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getThreadsList(courseID: String, type: ThreadType, sort: SortType, filter: ThreadsFilter, page: Int). Use given") - Failure("Stub return value not specified for getThreadsList(courseID: String, type: ThreadType, sort: SortType, filter: ThreadsFilter, page: Int). Use given") - } catch { - throw error - } - return __value - } - - open func getTopics(courseID: String) throws -> Topics { - addInvocation(.m_getTopics__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getTopics__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: Topics - do { - __value = try methodReturnValue(.m_getTopics__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getTopics(courseID: String). Use given") - Failure("Stub return value not specified for getTopics(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getTopic(courseID: String, topicID: String) throws -> Topics { - addInvocation(.m_getTopic__courseID_courseIDtopicID_topicID(Parameter.value(`courseID`), Parameter.value(`topicID`))) - let perform = methodPerformValue(.m_getTopic__courseID_courseIDtopicID_topicID(Parameter.value(`courseID`), Parameter.value(`topicID`))) as? (String, String) -> Void - perform?(`courseID`, `topicID`) - var __value: Topics - do { - __value = try methodReturnValue(.m_getTopic__courseID_courseIDtopicID_topicID(Parameter.value(`courseID`), Parameter.value(`topicID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getTopic(courseID: String, topicID: String). Use given") - Failure("Stub return value not specified for getTopic(courseID: String, topicID: String). Use given") - } catch { - throw error - } - return __value - } - - open func searchThreads(courseID: String, searchText: String, pageNumber: Int) throws -> ThreadLists { - addInvocation(.m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber(Parameter.value(`courseID`), Parameter.value(`searchText`), Parameter.value(`pageNumber`))) - let perform = methodPerformValue(.m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber(Parameter.value(`courseID`), Parameter.value(`searchText`), Parameter.value(`pageNumber`))) as? (String, String, Int) -> Void - perform?(`courseID`, `searchText`, `pageNumber`) - var __value: ThreadLists - do { - __value = try methodReturnValue(.m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber(Parameter.value(`courseID`), Parameter.value(`searchText`), Parameter.value(`pageNumber`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for searchThreads(courseID: String, searchText: String, pageNumber: Int). Use given") - Failure("Stub return value not specified for searchThreads(courseID: String, searchText: String, pageNumber: Int). Use given") - } catch { - throw error - } - return __value - } - - open func getThread(threadID: String) throws -> UserThread { - addInvocation(.m_getThread__threadID_threadID(Parameter.value(`threadID`))) - let perform = methodPerformValue(.m_getThread__threadID_threadID(Parameter.value(`threadID`))) as? (String) -> Void - perform?(`threadID`) - var __value: UserThread - do { - __value = try methodReturnValue(.m_getThread__threadID_threadID(Parameter.value(`threadID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getThread(threadID: String). Use given") - Failure("Stub return value not specified for getThread(threadID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getDiscussionComments(threadID: String, page: Int) throws -> ([UserComment], Pagination) { - addInvocation(.m_getDiscussionComments__threadID_threadIDpage_page(Parameter.value(`threadID`), Parameter.value(`page`))) - let perform = methodPerformValue(.m_getDiscussionComments__threadID_threadIDpage_page(Parameter.value(`threadID`), Parameter.value(`page`))) as? (String, Int) -> Void - perform?(`threadID`, `page`) - var __value: ([UserComment], Pagination) - do { - __value = try methodReturnValue(.m_getDiscussionComments__threadID_threadIDpage_page(Parameter.value(`threadID`), Parameter.value(`page`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getDiscussionComments(threadID: String, page: Int). Use given") - Failure("Stub return value not specified for getDiscussionComments(threadID: String, page: Int). Use given") - } catch { - throw error - } - return __value - } - - open func getQuestionComments(threadID: String, page: Int) throws -> ([UserComment], Pagination) { - addInvocation(.m_getQuestionComments__threadID_threadIDpage_page(Parameter.value(`threadID`), Parameter.value(`page`))) - let perform = methodPerformValue(.m_getQuestionComments__threadID_threadIDpage_page(Parameter.value(`threadID`), Parameter.value(`page`))) as? (String, Int) -> Void - perform?(`threadID`, `page`) - var __value: ([UserComment], Pagination) - do { - __value = try methodReturnValue(.m_getQuestionComments__threadID_threadIDpage_page(Parameter.value(`threadID`), Parameter.value(`page`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getQuestionComments(threadID: String, page: Int). Use given") - Failure("Stub return value not specified for getQuestionComments(threadID: String, page: Int). Use given") - } catch { - throw error - } - return __value - } - - open func getCommentResponses(commentID: String, page: Int) throws -> ([UserComment], Pagination) { - addInvocation(.m_getCommentResponses__commentID_commentIDpage_page(Parameter.value(`commentID`), Parameter.value(`page`))) - let perform = methodPerformValue(.m_getCommentResponses__commentID_commentIDpage_page(Parameter.value(`commentID`), Parameter.value(`page`))) as? (String, Int) -> Void - perform?(`commentID`, `page`) - var __value: ([UserComment], Pagination) - do { - __value = try methodReturnValue(.m_getCommentResponses__commentID_commentIDpage_page(Parameter.value(`commentID`), Parameter.value(`page`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCommentResponses(commentID: String, page: Int). Use given") - Failure("Stub return value not specified for getCommentResponses(commentID: String, page: Int). Use given") - } catch { - throw error - } - return __value - } - - open func getResponse(responseID: String) throws -> UserComment { - addInvocation(.m_getResponse__responseID_responseID(Parameter.value(`responseID`))) - let perform = methodPerformValue(.m_getResponse__responseID_responseID(Parameter.value(`responseID`))) as? (String) -> Void - perform?(`responseID`) - var __value: UserComment - do { - __value = try methodReturnValue(.m_getResponse__responseID_responseID(Parameter.value(`responseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getResponse(responseID: String). Use given") - Failure("Stub return value not specified for getResponse(responseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func addCommentTo(threadID: String, rawBody: String, parentID: String?) throws -> Post { - addInvocation(.m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID(Parameter.value(`threadID`), Parameter.value(`rawBody`), Parameter.value(`parentID`))) - let perform = methodPerformValue(.m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID(Parameter.value(`threadID`), Parameter.value(`rawBody`), Parameter.value(`parentID`))) as? (String, String, String?) -> Void - perform?(`threadID`, `rawBody`, `parentID`) - var __value: Post - do { - __value = try methodReturnValue(.m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID(Parameter.value(`threadID`), Parameter.value(`rawBody`), Parameter.value(`parentID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for addCommentTo(threadID: String, rawBody: String, parentID: String?). Use given") - Failure("Stub return value not specified for addCommentTo(threadID: String, rawBody: String, parentID: String?). Use given") - } catch { - throw error - } - return __value - } - - open func voteThread(voted: Bool, threadID: String) throws { - addInvocation(.m_voteThread__voted_votedthreadID_threadID(Parameter.value(`voted`), Parameter.value(`threadID`))) - let perform = methodPerformValue(.m_voteThread__voted_votedthreadID_threadID(Parameter.value(`voted`), Parameter.value(`threadID`))) as? (Bool, String) -> Void - perform?(`voted`, `threadID`) - do { - _ = try methodReturnValue(.m_voteThread__voted_votedthreadID_threadID(Parameter.value(`voted`), Parameter.value(`threadID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func voteResponse(voted: Bool, responseID: String) throws { - addInvocation(.m_voteResponse__voted_votedresponseID_responseID(Parameter.value(`voted`), Parameter.value(`responseID`))) - let perform = methodPerformValue(.m_voteResponse__voted_votedresponseID_responseID(Parameter.value(`voted`), Parameter.value(`responseID`))) as? (Bool, String) -> Void - perform?(`voted`, `responseID`) - do { - _ = try methodReturnValue(.m_voteResponse__voted_votedresponseID_responseID(Parameter.value(`voted`), Parameter.value(`responseID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func flagThread(abuseFlagged: Bool, threadID: String) throws { - addInvocation(.m_flagThread__abuseFlagged_abuseFlaggedthreadID_threadID(Parameter.value(`abuseFlagged`), Parameter.value(`threadID`))) - let perform = methodPerformValue(.m_flagThread__abuseFlagged_abuseFlaggedthreadID_threadID(Parameter.value(`abuseFlagged`), Parameter.value(`threadID`))) as? (Bool, String) -> Void - perform?(`abuseFlagged`, `threadID`) - do { - _ = try methodReturnValue(.m_flagThread__abuseFlagged_abuseFlaggedthreadID_threadID(Parameter.value(`abuseFlagged`), Parameter.value(`threadID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func flagComment(abuseFlagged: Bool, commentID: String) throws { - addInvocation(.m_flagComment__abuseFlagged_abuseFlaggedcommentID_commentID(Parameter.value(`abuseFlagged`), Parameter.value(`commentID`))) - let perform = methodPerformValue(.m_flagComment__abuseFlagged_abuseFlaggedcommentID_commentID(Parameter.value(`abuseFlagged`), Parameter.value(`commentID`))) as? (Bool, String) -> Void - perform?(`abuseFlagged`, `commentID`) - do { - _ = try methodReturnValue(.m_flagComment__abuseFlagged_abuseFlaggedcommentID_commentID(Parameter.value(`abuseFlagged`), Parameter.value(`commentID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func followThread(following: Bool, threadID: String) throws { - addInvocation(.m_followThread__following_followingthreadID_threadID(Parameter.value(`following`), Parameter.value(`threadID`))) - let perform = methodPerformValue(.m_followThread__following_followingthreadID_threadID(Parameter.value(`following`), Parameter.value(`threadID`))) as? (Bool, String) -> Void - perform?(`following`, `threadID`) - do { - _ = try methodReturnValue(.m_followThread__following_followingthreadID_threadID(Parameter.value(`following`), Parameter.value(`threadID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func createNewThread(newThread: DiscussionNewThread) throws { - addInvocation(.m_createNewThread__newThread_newThread(Parameter.value(`newThread`))) - let perform = methodPerformValue(.m_createNewThread__newThread_newThread(Parameter.value(`newThread`))) as? (DiscussionNewThread) -> Void - perform?(`newThread`) - do { - _ = try methodReturnValue(.m_createNewThread__newThread_newThread(Parameter.value(`newThread`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func readBody(threadID: String) throws { - addInvocation(.m_readBody__threadID_threadID(Parameter.value(`threadID`))) - let perform = methodPerformValue(.m_readBody__threadID_threadID(Parameter.value(`threadID`))) as? (String) -> Void - perform?(`threadID`) - do { - _ = try methodReturnValue(.m_readBody__threadID_threadID(Parameter.value(`threadID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - - fileprivate enum MethodType { - case m_getCourseDiscussionInfo__courseID_courseID(Parameter) - case m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page(Parameter, Parameter, Parameter, Parameter, Parameter) - case m_getTopics__courseID_courseID(Parameter) - case m_getTopic__courseID_courseIDtopicID_topicID(Parameter, Parameter) - case m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber(Parameter, Parameter, Parameter) - case m_getThread__threadID_threadID(Parameter) - case m_getDiscussionComments__threadID_threadIDpage_page(Parameter, Parameter) - case m_getQuestionComments__threadID_threadIDpage_page(Parameter, Parameter) - case m_getCommentResponses__commentID_commentIDpage_page(Parameter, Parameter) - case m_getResponse__responseID_responseID(Parameter) - case m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID(Parameter, Parameter, Parameter) - case m_voteThread__voted_votedthreadID_threadID(Parameter, Parameter) - case m_voteResponse__voted_votedresponseID_responseID(Parameter, Parameter) - case m_flagThread__abuseFlagged_abuseFlaggedthreadID_threadID(Parameter, Parameter) - case m_flagComment__abuseFlagged_abuseFlaggedcommentID_commentID(Parameter, Parameter) - case m_followThread__following_followingthreadID_threadID(Parameter, Parameter) - case m_createNewThread__newThread_newThread(Parameter) - case m_readBody__threadID_threadID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseDiscussionInfo__courseID_courseID(let lhsCourseid), .m_getCourseDiscussionInfo__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page(let lhsCourseid, let lhsType, let lhsSort, let lhsFilter, let lhsPage), .m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page(let rhsCourseid, let rhsType, let rhsSort, let rhsFilter, let rhsPage)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSort, rhs: rhsSort, with: matcher), lhsSort, rhsSort, "sort")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFilter, rhs: rhsFilter, with: matcher), lhsFilter, rhsFilter, "filter")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPage, rhs: rhsPage, with: matcher), lhsPage, rhsPage, "page")) - return Matcher.ComparisonResult(results) - - case (.m_getTopics__courseID_courseID(let lhsCourseid), .m_getTopics__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getTopic__courseID_courseIDtopicID_topicID(let lhsCourseid, let lhsTopicid), .m_getTopic__courseID_courseIDtopicID_topicID(let rhsCourseid, let rhsTopicid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTopicid, rhs: rhsTopicid, with: matcher), lhsTopicid, rhsTopicid, "topicID")) - return Matcher.ComparisonResult(results) - - case (.m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber(let lhsCourseid, let lhsSearchtext, let lhsPagenumber), .m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber(let rhsCourseid, let rhsSearchtext, let rhsPagenumber)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchtext, rhs: rhsSearchtext, with: matcher), lhsSearchtext, rhsSearchtext, "searchText")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPagenumber, rhs: rhsPagenumber, with: matcher), lhsPagenumber, rhsPagenumber, "pageNumber")) - return Matcher.ComparisonResult(results) - - case (.m_getThread__threadID_threadID(let lhsThreadid), .m_getThread__threadID_threadID(let rhsThreadid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - return Matcher.ComparisonResult(results) - - case (.m_getDiscussionComments__threadID_threadIDpage_page(let lhsThreadid, let lhsPage), .m_getDiscussionComments__threadID_threadIDpage_page(let rhsThreadid, let rhsPage)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPage, rhs: rhsPage, with: matcher), lhsPage, rhsPage, "page")) - return Matcher.ComparisonResult(results) - - case (.m_getQuestionComments__threadID_threadIDpage_page(let lhsThreadid, let lhsPage), .m_getQuestionComments__threadID_threadIDpage_page(let rhsThreadid, let rhsPage)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPage, rhs: rhsPage, with: matcher), lhsPage, rhsPage, "page")) - return Matcher.ComparisonResult(results) - - case (.m_getCommentResponses__commentID_commentIDpage_page(let lhsCommentid, let lhsPage), .m_getCommentResponses__commentID_commentIDpage_page(let rhsCommentid, let rhsPage)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCommentid, rhs: rhsCommentid, with: matcher), lhsCommentid, rhsCommentid, "commentID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPage, rhs: rhsPage, with: matcher), lhsPage, rhsPage, "page")) - return Matcher.ComparisonResult(results) - - case (.m_getResponse__responseID_responseID(let lhsResponseid), .m_getResponse__responseID_responseID(let rhsResponseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsResponseid, rhs: rhsResponseid, with: matcher), lhsResponseid, rhsResponseid, "responseID")) - return Matcher.ComparisonResult(results) - - case (.m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID(let lhsThreadid, let lhsRawbody, let lhsParentid), .m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID(let rhsThreadid, let rhsRawbody, let rhsParentid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRawbody, rhs: rhsRawbody, with: matcher), lhsRawbody, rhsRawbody, "rawBody")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParentid, rhs: rhsParentid, with: matcher), lhsParentid, rhsParentid, "parentID")) - return Matcher.ComparisonResult(results) - - case (.m_voteThread__voted_votedthreadID_threadID(let lhsVoted, let lhsThreadid), .m_voteThread__voted_votedthreadID_threadID(let rhsVoted, let rhsThreadid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsVoted, rhs: rhsVoted, with: matcher), lhsVoted, rhsVoted, "voted")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - return Matcher.ComparisonResult(results) - - case (.m_voteResponse__voted_votedresponseID_responseID(let lhsVoted, let lhsResponseid), .m_voteResponse__voted_votedresponseID_responseID(let rhsVoted, let rhsResponseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsVoted, rhs: rhsVoted, with: matcher), lhsVoted, rhsVoted, "voted")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsResponseid, rhs: rhsResponseid, with: matcher), lhsResponseid, rhsResponseid, "responseID")) - return Matcher.ComparisonResult(results) - - case (.m_flagThread__abuseFlagged_abuseFlaggedthreadID_threadID(let lhsAbuseflagged, let lhsThreadid), .m_flagThread__abuseFlagged_abuseFlaggedthreadID_threadID(let rhsAbuseflagged, let rhsThreadid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAbuseflagged, rhs: rhsAbuseflagged, with: matcher), lhsAbuseflagged, rhsAbuseflagged, "abuseFlagged")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - return Matcher.ComparisonResult(results) - - case (.m_flagComment__abuseFlagged_abuseFlaggedcommentID_commentID(let lhsAbuseflagged, let lhsCommentid), .m_flagComment__abuseFlagged_abuseFlaggedcommentID_commentID(let rhsAbuseflagged, let rhsCommentid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAbuseflagged, rhs: rhsAbuseflagged, with: matcher), lhsAbuseflagged, rhsAbuseflagged, "abuseFlagged")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCommentid, rhs: rhsCommentid, with: matcher), lhsCommentid, rhsCommentid, "commentID")) - return Matcher.ComparisonResult(results) - - case (.m_followThread__following_followingthreadID_threadID(let lhsFollowing, let lhsThreadid), .m_followThread__following_followingthreadID_threadID(let rhsFollowing, let rhsThreadid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFollowing, rhs: rhsFollowing, with: matcher), lhsFollowing, rhsFollowing, "following")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - return Matcher.ComparisonResult(results) - - case (.m_createNewThread__newThread_newThread(let lhsNewthread), .m_createNewThread__newThread_newThread(let rhsNewthread)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNewthread, rhs: rhsNewthread, with: matcher), lhsNewthread, rhsNewthread, "newThread")) - return Matcher.ComparisonResult(results) - - case (.m_readBody__threadID_threadID(let lhsThreadid), .m_readBody__threadID_threadID(let rhsThreadid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadid, rhs: rhsThreadid, with: matcher), lhsThreadid, rhsThreadid, "threadID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseDiscussionInfo__courseID_courseID(p0): return p0.intValue - case let .m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page(p0, p1, p2, p3, p4): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue - case let .m_getTopics__courseID_courseID(p0): return p0.intValue - case let .m_getTopic__courseID_courseIDtopicID_topicID(p0, p1): return p0.intValue + p1.intValue - case let .m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_getThread__threadID_threadID(p0): return p0.intValue - case let .m_getDiscussionComments__threadID_threadIDpage_page(p0, p1): return p0.intValue + p1.intValue - case let .m_getQuestionComments__threadID_threadIDpage_page(p0, p1): return p0.intValue + p1.intValue - case let .m_getCommentResponses__commentID_commentIDpage_page(p0, p1): return p0.intValue + p1.intValue - case let .m_getResponse__responseID_responseID(p0): return p0.intValue - case let .m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_voteThread__voted_votedthreadID_threadID(p0, p1): return p0.intValue + p1.intValue - case let .m_voteResponse__voted_votedresponseID_responseID(p0, p1): return p0.intValue + p1.intValue - case let .m_flagThread__abuseFlagged_abuseFlaggedthreadID_threadID(p0, p1): return p0.intValue + p1.intValue - case let .m_flagComment__abuseFlagged_abuseFlaggedcommentID_commentID(p0, p1): return p0.intValue + p1.intValue - case let .m_followThread__following_followingthreadID_threadID(p0, p1): return p0.intValue + p1.intValue - case let .m_createNewThread__newThread_newThread(p0): return p0.intValue - case let .m_readBody__threadID_threadID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getCourseDiscussionInfo__courseID_courseID: return ".getCourseDiscussionInfo(courseID:)" - case .m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page: return ".getThreadsList(courseID:type:sort:filter:page:)" - case .m_getTopics__courseID_courseID: return ".getTopics(courseID:)" - case .m_getTopic__courseID_courseIDtopicID_topicID: return ".getTopic(courseID:topicID:)" - case .m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber: return ".searchThreads(courseID:searchText:pageNumber:)" - case .m_getThread__threadID_threadID: return ".getThread(threadID:)" - case .m_getDiscussionComments__threadID_threadIDpage_page: return ".getDiscussionComments(threadID:page:)" - case .m_getQuestionComments__threadID_threadIDpage_page: return ".getQuestionComments(threadID:page:)" - case .m_getCommentResponses__commentID_commentIDpage_page: return ".getCommentResponses(commentID:page:)" - case .m_getResponse__responseID_responseID: return ".getResponse(responseID:)" - case .m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID: return ".addCommentTo(threadID:rawBody:parentID:)" - case .m_voteThread__voted_votedthreadID_threadID: return ".voteThread(voted:threadID:)" - case .m_voteResponse__voted_votedresponseID_responseID: return ".voteResponse(voted:responseID:)" - case .m_flagThread__abuseFlagged_abuseFlaggedthreadID_threadID: return ".flagThread(abuseFlagged:threadID:)" - case .m_flagComment__abuseFlagged_abuseFlaggedcommentID_commentID: return ".flagComment(abuseFlagged:commentID:)" - case .m_followThread__following_followingthreadID_threadID: return ".followThread(following:threadID:)" - case .m_createNewThread__newThread_newThread: return ".createNewThread(newThread:)" - case .m_readBody__threadID_threadID: return ".readBody(threadID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseDiscussionInfo(courseID: Parameter, willReturn: DiscussionInfo...) -> MethodStub { - return Given(method: .m_getCourseDiscussionInfo__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getThreadsList(courseID: Parameter, type: Parameter, sort: Parameter, filter: Parameter, page: Parameter, willReturn: ThreadLists...) -> MethodStub { - return Given(method: .m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page(`courseID`, `type`, `sort`, `filter`, `page`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getTopics(courseID: Parameter, willReturn: Topics...) -> MethodStub { - return Given(method: .m_getTopics__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getTopic(courseID: Parameter, topicID: Parameter, willReturn: Topics...) -> MethodStub { - return Given(method: .m_getTopic__courseID_courseIDtopicID_topicID(`courseID`, `topicID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func searchThreads(courseID: Parameter, searchText: Parameter, pageNumber: Parameter, willReturn: ThreadLists...) -> MethodStub { - return Given(method: .m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber(`courseID`, `searchText`, `pageNumber`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getThread(threadID: Parameter, willReturn: UserThread...) -> MethodStub { - return Given(method: .m_getThread__threadID_threadID(`threadID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDiscussionComments(threadID: Parameter, page: Parameter, willReturn: ([UserComment], Pagination)...) -> MethodStub { - return Given(method: .m_getDiscussionComments__threadID_threadIDpage_page(`threadID`, `page`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getQuestionComments(threadID: Parameter, page: Parameter, willReturn: ([UserComment], Pagination)...) -> MethodStub { - return Given(method: .m_getQuestionComments__threadID_threadIDpage_page(`threadID`, `page`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCommentResponses(commentID: Parameter, page: Parameter, willReturn: ([UserComment], Pagination)...) -> MethodStub { - return Given(method: .m_getCommentResponses__commentID_commentIDpage_page(`commentID`, `page`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getResponse(responseID: Parameter, willReturn: UserComment...) -> MethodStub { - return Given(method: .m_getResponse__responseID_responseID(`responseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func addCommentTo(threadID: Parameter, rawBody: Parameter, parentID: Parameter, willReturn: Post...) -> MethodStub { - return Given(method: .m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID(`threadID`, `rawBody`, `parentID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseDiscussionInfo(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseDiscussionInfo__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseDiscussionInfo(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseDiscussionInfo__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (DiscussionInfo).self) - willProduce(stubber) - return given - } - public static func getThreadsList(courseID: Parameter, type: Parameter, sort: Parameter, filter: Parameter, page: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page(`courseID`, `type`, `sort`, `filter`, `page`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getThreadsList(courseID: Parameter, type: Parameter, sort: Parameter, filter: Parameter, page: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page(`courseID`, `type`, `sort`, `filter`, `page`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (ThreadLists).self) - willProduce(stubber) - return given - } - public static func getTopics(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getTopics__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getTopics(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getTopics__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Topics).self) - willProduce(stubber) - return given - } - public static func getTopic(courseID: Parameter, topicID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getTopic__courseID_courseIDtopicID_topicID(`courseID`, `topicID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getTopic(courseID: Parameter, topicID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getTopic__courseID_courseIDtopicID_topicID(`courseID`, `topicID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Topics).self) - willProduce(stubber) - return given - } - public static func searchThreads(courseID: Parameter, searchText: Parameter, pageNumber: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber(`courseID`, `searchText`, `pageNumber`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func searchThreads(courseID: Parameter, searchText: Parameter, pageNumber: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber(`courseID`, `searchText`, `pageNumber`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (ThreadLists).self) - willProduce(stubber) - return given - } - public static func getThread(threadID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getThread__threadID_threadID(`threadID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getThread(threadID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getThread__threadID_threadID(`threadID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (UserThread).self) - willProduce(stubber) - return given - } - public static func getDiscussionComments(threadID: Parameter, page: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getDiscussionComments__threadID_threadIDpage_page(`threadID`, `page`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getDiscussionComments(threadID: Parameter, page: Parameter, willProduce: (StubberThrows<([UserComment], Pagination)>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getDiscussionComments__threadID_threadIDpage_page(`threadID`, `page`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (([UserComment], Pagination)).self) - willProduce(stubber) - return given - } - public static func getQuestionComments(threadID: Parameter, page: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getQuestionComments__threadID_threadIDpage_page(`threadID`, `page`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getQuestionComments(threadID: Parameter, page: Parameter, willProduce: (StubberThrows<([UserComment], Pagination)>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getQuestionComments__threadID_threadIDpage_page(`threadID`, `page`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (([UserComment], Pagination)).self) - willProduce(stubber) - return given - } - public static func getCommentResponses(commentID: Parameter, page: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCommentResponses__commentID_commentIDpage_page(`commentID`, `page`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCommentResponses(commentID: Parameter, page: Parameter, willProduce: (StubberThrows<([UserComment], Pagination)>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCommentResponses__commentID_commentIDpage_page(`commentID`, `page`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (([UserComment], Pagination)).self) - willProduce(stubber) - return given - } - public static func getResponse(responseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getResponse__responseID_responseID(`responseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getResponse(responseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getResponse__responseID_responseID(`responseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (UserComment).self) - willProduce(stubber) - return given - } - public static func addCommentTo(threadID: Parameter, rawBody: Parameter, parentID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID(`threadID`, `rawBody`, `parentID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func addCommentTo(threadID: Parameter, rawBody: Parameter, parentID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID(`threadID`, `rawBody`, `parentID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Post).self) - willProduce(stubber) - return given - } - public static func voteThread(voted: Parameter, threadID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_voteThread__voted_votedthreadID_threadID(`voted`, `threadID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func voteThread(voted: Parameter, threadID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_voteThread__voted_votedthreadID_threadID(`voted`, `threadID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func voteResponse(voted: Parameter, responseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_voteResponse__voted_votedresponseID_responseID(`voted`, `responseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func voteResponse(voted: Parameter, responseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_voteResponse__voted_votedresponseID_responseID(`voted`, `responseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func flagThread(abuseFlagged: Parameter, threadID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_flagThread__abuseFlagged_abuseFlaggedthreadID_threadID(`abuseFlagged`, `threadID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func flagThread(abuseFlagged: Parameter, threadID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_flagThread__abuseFlagged_abuseFlaggedthreadID_threadID(`abuseFlagged`, `threadID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func flagComment(abuseFlagged: Parameter, commentID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_flagComment__abuseFlagged_abuseFlaggedcommentID_commentID(`abuseFlagged`, `commentID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func flagComment(abuseFlagged: Parameter, commentID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_flagComment__abuseFlagged_abuseFlaggedcommentID_commentID(`abuseFlagged`, `commentID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func followThread(following: Parameter, threadID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_followThread__following_followingthreadID_threadID(`following`, `threadID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func followThread(following: Parameter, threadID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_followThread__following_followingthreadID_threadID(`following`, `threadID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func createNewThread(newThread: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_createNewThread__newThread_newThread(`newThread`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func createNewThread(newThread: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_createNewThread__newThread_newThread(`newThread`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func readBody(threadID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_readBody__threadID_threadID(`threadID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func readBody(threadID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_readBody__threadID_threadID(`threadID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseDiscussionInfo(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseDiscussionInfo__courseID_courseID(`courseID`))} - public static func getThreadsList(courseID: Parameter, type: Parameter, sort: Parameter, filter: Parameter, page: Parameter) -> Verify { return Verify(method: .m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page(`courseID`, `type`, `sort`, `filter`, `page`))} - public static func getTopics(courseID: Parameter) -> Verify { return Verify(method: .m_getTopics__courseID_courseID(`courseID`))} - public static func getTopic(courseID: Parameter, topicID: Parameter) -> Verify { return Verify(method: .m_getTopic__courseID_courseIDtopicID_topicID(`courseID`, `topicID`))} - public static func searchThreads(courseID: Parameter, searchText: Parameter, pageNumber: Parameter) -> Verify { return Verify(method: .m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber(`courseID`, `searchText`, `pageNumber`))} - public static func getThread(threadID: Parameter) -> Verify { return Verify(method: .m_getThread__threadID_threadID(`threadID`))} - public static func getDiscussionComments(threadID: Parameter, page: Parameter) -> Verify { return Verify(method: .m_getDiscussionComments__threadID_threadIDpage_page(`threadID`, `page`))} - public static func getQuestionComments(threadID: Parameter, page: Parameter) -> Verify { return Verify(method: .m_getQuestionComments__threadID_threadIDpage_page(`threadID`, `page`))} - public static func getCommentResponses(commentID: Parameter, page: Parameter) -> Verify { return Verify(method: .m_getCommentResponses__commentID_commentIDpage_page(`commentID`, `page`))} - public static func getResponse(responseID: Parameter) -> Verify { return Verify(method: .m_getResponse__responseID_responseID(`responseID`))} - public static func addCommentTo(threadID: Parameter, rawBody: Parameter, parentID: Parameter) -> Verify { return Verify(method: .m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID(`threadID`, `rawBody`, `parentID`))} - public static func voteThread(voted: Parameter, threadID: Parameter) -> Verify { return Verify(method: .m_voteThread__voted_votedthreadID_threadID(`voted`, `threadID`))} - public static func voteResponse(voted: Parameter, responseID: Parameter) -> Verify { return Verify(method: .m_voteResponse__voted_votedresponseID_responseID(`voted`, `responseID`))} - public static func flagThread(abuseFlagged: Parameter, threadID: Parameter) -> Verify { return Verify(method: .m_flagThread__abuseFlagged_abuseFlaggedthreadID_threadID(`abuseFlagged`, `threadID`))} - public static func flagComment(abuseFlagged: Parameter, commentID: Parameter) -> Verify { return Verify(method: .m_flagComment__abuseFlagged_abuseFlaggedcommentID_commentID(`abuseFlagged`, `commentID`))} - public static func followThread(following: Parameter, threadID: Parameter) -> Verify { return Verify(method: .m_followThread__following_followingthreadID_threadID(`following`, `threadID`))} - public static func createNewThread(newThread: Parameter) -> Verify { return Verify(method: .m_createNewThread__newThread_newThread(`newThread`))} - public static func readBody(threadID: Parameter) -> Verify { return Verify(method: .m_readBody__threadID_threadID(`threadID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseDiscussionInfo(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseDiscussionInfo__courseID_courseID(`courseID`), performs: perform) - } - public static func getThreadsList(courseID: Parameter, type: Parameter, sort: Parameter, filter: Parameter, page: Parameter, perform: @escaping (String, ThreadType, SortType, ThreadsFilter, Int) -> Void) -> Perform { - return Perform(method: .m_getThreadsList__courseID_courseIDtype_typesort_sortfilter_filterpage_page(`courseID`, `type`, `sort`, `filter`, `page`), performs: perform) - } - public static func getTopics(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getTopics__courseID_courseID(`courseID`), performs: perform) - } - public static func getTopic(courseID: Parameter, topicID: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_getTopic__courseID_courseIDtopicID_topicID(`courseID`, `topicID`), performs: perform) - } - public static func searchThreads(courseID: Parameter, searchText: Parameter, pageNumber: Parameter, perform: @escaping (String, String, Int) -> Void) -> Perform { - return Perform(method: .m_searchThreads__courseID_courseIDsearchText_searchTextpageNumber_pageNumber(`courseID`, `searchText`, `pageNumber`), performs: perform) - } - public static func getThread(threadID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getThread__threadID_threadID(`threadID`), performs: perform) - } - public static func getDiscussionComments(threadID: Parameter, page: Parameter, perform: @escaping (String, Int) -> Void) -> Perform { - return Perform(method: .m_getDiscussionComments__threadID_threadIDpage_page(`threadID`, `page`), performs: perform) - } - public static func getQuestionComments(threadID: Parameter, page: Parameter, perform: @escaping (String, Int) -> Void) -> Perform { - return Perform(method: .m_getQuestionComments__threadID_threadIDpage_page(`threadID`, `page`), performs: perform) - } - public static func getCommentResponses(commentID: Parameter, page: Parameter, perform: @escaping (String, Int) -> Void) -> Perform { - return Perform(method: .m_getCommentResponses__commentID_commentIDpage_page(`commentID`, `page`), performs: perform) - } - public static func getResponse(responseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getResponse__responseID_responseID(`responseID`), performs: perform) - } - public static func addCommentTo(threadID: Parameter, rawBody: Parameter, parentID: Parameter, perform: @escaping (String, String, String?) -> Void) -> Perform { - return Perform(method: .m_addCommentTo__threadID_threadIDrawBody_rawBodyparentID_parentID(`threadID`, `rawBody`, `parentID`), performs: perform) - } - public static func voteThread(voted: Parameter, threadID: Parameter, perform: @escaping (Bool, String) -> Void) -> Perform { - return Perform(method: .m_voteThread__voted_votedthreadID_threadID(`voted`, `threadID`), performs: perform) - } - public static func voteResponse(voted: Parameter, responseID: Parameter, perform: @escaping (Bool, String) -> Void) -> Perform { - return Perform(method: .m_voteResponse__voted_votedresponseID_responseID(`voted`, `responseID`), performs: perform) - } - public static func flagThread(abuseFlagged: Parameter, threadID: Parameter, perform: @escaping (Bool, String) -> Void) -> Perform { - return Perform(method: .m_flagThread__abuseFlagged_abuseFlaggedthreadID_threadID(`abuseFlagged`, `threadID`), performs: perform) - } - public static func flagComment(abuseFlagged: Parameter, commentID: Parameter, perform: @escaping (Bool, String) -> Void) -> Perform { - return Perform(method: .m_flagComment__abuseFlagged_abuseFlaggedcommentID_commentID(`abuseFlagged`, `commentID`), performs: perform) - } - public static func followThread(following: Parameter, threadID: Parameter, perform: @escaping (Bool, String) -> Void) -> Perform { - return Perform(method: .m_followThread__following_followingthreadID_threadID(`following`, `threadID`), performs: perform) - } - public static func createNewThread(newThread: Parameter, perform: @escaping (DiscussionNewThread) -> Void) -> Perform { - return Perform(method: .m_createNewThread__newThread_newThread(`newThread`), performs: perform) - } - public static func readBody(threadID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_readBody__threadID_threadID(`threadID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DiscussionRouter -@MainActor -open class DiscussionRouterMock: DiscussionRouter, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func showUserDetails(username: String) { - addInvocation(.m_showUserDetails__username_username(Parameter.value(`username`))) - let perform = methodPerformValue(.m_showUserDetails__username_username(Parameter.value(`username`))) as? (String) -> Void - perform?(`username`) - } - - open func showThreads(courseID: String, topics: Topics, title: String, type: ThreadType, isBlackedOut: Bool, animated: Bool) { - addInvocation(.m_showThreads__courseID_courseIDtopics_topicstitle_titletype_typeisBlackedOut_isBlackedOutanimated_animated(Parameter.value(`courseID`), Parameter.value(`topics`), Parameter.value(`title`), Parameter.value(`type`), Parameter.value(`isBlackedOut`), Parameter.value(`animated`))) - let perform = methodPerformValue(.m_showThreads__courseID_courseIDtopics_topicstitle_titletype_typeisBlackedOut_isBlackedOutanimated_animated(Parameter.value(`courseID`), Parameter.value(`topics`), Parameter.value(`title`), Parameter.value(`type`), Parameter.value(`isBlackedOut`), Parameter.value(`animated`))) as? (String, Topics, String, ThreadType, Bool, Bool) -> Void - perform?(`courseID`, `topics`, `title`, `type`, `isBlackedOut`, `animated`) - } - - open func showThread(thread: UserThread, postStateSubject: CurrentValueSubject, isBlackedOut: Bool, animated: Bool) { - addInvocation(.m_showThread__thread_threadpostStateSubject_postStateSubjectisBlackedOut_isBlackedOutanimated_animated(Parameter.value(`thread`), Parameter>.value(`postStateSubject`), Parameter.value(`isBlackedOut`), Parameter.value(`animated`))) - let perform = methodPerformValue(.m_showThread__thread_threadpostStateSubject_postStateSubjectisBlackedOut_isBlackedOutanimated_animated(Parameter.value(`thread`), Parameter>.value(`postStateSubject`), Parameter.value(`isBlackedOut`), Parameter.value(`animated`))) as? (UserThread, CurrentValueSubject, Bool, Bool) -> Void - perform?(`thread`, `postStateSubject`, `isBlackedOut`, `animated`) - } - - open func showDiscussionsSearch(courseID: String, isBlackedOut: Bool) { - addInvocation(.m_showDiscussionsSearch__courseID_courseIDisBlackedOut_isBlackedOut(Parameter.value(`courseID`), Parameter.value(`isBlackedOut`))) - let perform = methodPerformValue(.m_showDiscussionsSearch__courseID_courseIDisBlackedOut_isBlackedOut(Parameter.value(`courseID`), Parameter.value(`isBlackedOut`))) as? (String, Bool) -> Void - perform?(`courseID`, `isBlackedOut`) - } - - open func showComments(courseID: String, commentID: String, parentComment: Post, threadStateSubject: CurrentValueSubject, isBlackedOut: Bool, animated: Bool) { - addInvocation(.m_showComments__courseID_courseIDcommentID_commentIDparentComment_parentCommentthreadStateSubject_threadStateSubjectisBlackedOut_isBlackedOutanimated_animated(Parameter.value(`courseID`), Parameter.value(`commentID`), Parameter.value(`parentComment`), Parameter>.value(`threadStateSubject`), Parameter.value(`isBlackedOut`), Parameter.value(`animated`))) - let perform = methodPerformValue(.m_showComments__courseID_courseIDcommentID_commentIDparentComment_parentCommentthreadStateSubject_threadStateSubjectisBlackedOut_isBlackedOutanimated_animated(Parameter.value(`courseID`), Parameter.value(`commentID`), Parameter.value(`parentComment`), Parameter>.value(`threadStateSubject`), Parameter.value(`isBlackedOut`), Parameter.value(`animated`))) as? (String, String, Post, CurrentValueSubject, Bool, Bool) -> Void - perform?(`courseID`, `commentID`, `parentComment`, `threadStateSubject`, `isBlackedOut`, `animated`) - } - - open func createNewThread(courseID: String, selectedTopic: String, onPostCreated: @escaping () -> Void) { - addInvocation(.m_createNewThread__courseID_courseIDselectedTopic_selectedTopiconPostCreated_onPostCreated(Parameter.value(`courseID`), Parameter.value(`selectedTopic`), Parameter<() -> Void>.value(`onPostCreated`))) - let perform = methodPerformValue(.m_createNewThread__courseID_courseIDselectedTopic_selectedTopiconPostCreated_onPostCreated(Parameter.value(`courseID`), Parameter.value(`selectedTopic`), Parameter<() -> Void>.value(`onPostCreated`))) as? (String, String, @escaping () -> Void) -> Void - perform?(`courseID`, `selectedTopic`, `onPostCreated`) - } - - open func backToRoot(animated: Bool) { - addInvocation(.m_backToRoot__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_backToRoot__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func back(animated: Bool) { - addInvocation(.m_back__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_back__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func backWithFade() { - addInvocation(.m_backWithFade) - let perform = methodPerformValue(.m_backWithFade) as? () -> Void - perform?() - } - - open func dismiss(animated: Bool) { - addInvocation(.m_dismiss__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_dismiss__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func removeLastView(controllers: Int) { - addInvocation(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) - let perform = methodPerformValue(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) as? (Int) -> Void - perform?(`controllers`) - } - - open func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { - addInvocation(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) - let perform = methodPerformValue(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) as? (LogistrationSourceScreen, PostLoginData?) -> Void - perform?(`sourceScreen`, `postLoginData`) - } - - open func showStartupScreen() { - addInvocation(.m_showStartupScreen) - let perform = methodPerformValue(.m_showStartupScreen) as? () -> Void - perform?() - } - - open func showLoginScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showForgotPasswordScreen() { - addInvocation(.m_showForgotPasswordScreen) - let perform = methodPerformValue(.m_showForgotPasswordScreen) as? () -> Void - perform?() - } - - open func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) as? (String?, LogistrationSourceScreen) -> Void - perform?(`searchQuery`, `sourceScreen`) - } - - open func showWebBrowser(title: String, url: URL) { - addInvocation(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) - let perform = methodPerformValue(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) as? (String, URL) -> Void - perform?(`title`, `url`) - } - - open func showSSOWebBrowser(title: String) { - addInvocation(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) - let perform = methodPerformValue(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) as? (String) -> Void - perform?(`title`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) as? (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void - perform?(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) as? (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void - perform?(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { - addInvocation(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) as? (UIModalTransitionStyle, any View, (() -> Void)?) -> Void - perform?(`transitionStyle`, `view`, `completion`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { - addInvocation(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) as? (UIModalTransitionStyle, Bool, () -> any View) -> Void - perform?(`transitionStyle`, `animated`, `content`) - } - - - fileprivate enum MethodType { - case m_showUserDetails__username_username(Parameter) - case m_showThreads__courseID_courseIDtopics_topicstitle_titletype_typeisBlackedOut_isBlackedOutanimated_animated(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter) - case m_showThread__thread_threadpostStateSubject_postStateSubjectisBlackedOut_isBlackedOutanimated_animated(Parameter, Parameter>, Parameter, Parameter) - case m_showDiscussionsSearch__courseID_courseIDisBlackedOut_isBlackedOut(Parameter, Parameter) - case m_showComments__courseID_courseIDcommentID_commentIDparentComment_parentCommentthreadStateSubject_threadStateSubjectisBlackedOut_isBlackedOutanimated_animated(Parameter, Parameter, Parameter, Parameter>, Parameter, Parameter) - case m_createNewThread__courseID_courseIDselectedTopic_selectedTopiconPostCreated_onPostCreated(Parameter, Parameter, Parameter<() -> Void>) - case m_backToRoot__animated_animated(Parameter) - case m_back__animated_animated(Parameter) - case m_backWithFade - case m_dismiss__animated_animated(Parameter) - case m_removeLastView__controllers_controllers(Parameter) - case m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter, Parameter) - case m_showStartupScreen - case m_showLoginScreen__sourceScreen_sourceScreen(Parameter) - case m_showRegisterScreen__sourceScreen_sourceScreen(Parameter) - case m_showForgotPasswordScreen - case m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter, Parameter) - case m_showWebBrowser__title_titleurl_url(Parameter, Parameter) - case m_showSSOWebBrowser__title_title(Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter<() -> Void>) - case m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter, Parameter, Parameter<(() -> Void)?>) - case m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter, Parameter, Parameter<() -> any View>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_showUserDetails__username_username(let lhsUsername), .m_showUserDetails__username_username(let rhsUsername)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsername, rhs: rhsUsername, with: matcher), lhsUsername, rhsUsername, "username")) - return Matcher.ComparisonResult(results) - - case (.m_showThreads__courseID_courseIDtopics_topicstitle_titletype_typeisBlackedOut_isBlackedOutanimated_animated(let lhsCourseid, let lhsTopics, let lhsTitle, let lhsType, let lhsIsblackedout, let lhsAnimated), .m_showThreads__courseID_courseIDtopics_topicstitle_titletype_typeisBlackedOut_isBlackedOutanimated_animated(let rhsCourseid, let rhsTopics, let rhsTitle, let rhsType, let rhsIsblackedout, let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTopics, rhs: rhsTopics, with: matcher), lhsTopics, rhsTopics, "topics")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIsblackedout, rhs: rhsIsblackedout, with: matcher), lhsIsblackedout, rhsIsblackedout, "isBlackedOut")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_showThread__thread_threadpostStateSubject_postStateSubjectisBlackedOut_isBlackedOutanimated_animated(let lhsThread, let lhsPoststatesubject, let lhsIsblackedout, let lhsAnimated), .m_showThread__thread_threadpostStateSubject_postStateSubjectisBlackedOut_isBlackedOutanimated_animated(let rhsThread, let rhsPoststatesubject, let rhsIsblackedout, let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThread, rhs: rhsThread, with: matcher), lhsThread, rhsThread, "thread")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPoststatesubject, rhs: rhsPoststatesubject, with: matcher), lhsPoststatesubject, rhsPoststatesubject, "postStateSubject")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIsblackedout, rhs: rhsIsblackedout, with: matcher), lhsIsblackedout, rhsIsblackedout, "isBlackedOut")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_showDiscussionsSearch__courseID_courseIDisBlackedOut_isBlackedOut(let lhsCourseid, let lhsIsblackedout), .m_showDiscussionsSearch__courseID_courseIDisBlackedOut_isBlackedOut(let rhsCourseid, let rhsIsblackedout)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIsblackedout, rhs: rhsIsblackedout, with: matcher), lhsIsblackedout, rhsIsblackedout, "isBlackedOut")) - return Matcher.ComparisonResult(results) - - case (.m_showComments__courseID_courseIDcommentID_commentIDparentComment_parentCommentthreadStateSubject_threadStateSubjectisBlackedOut_isBlackedOutanimated_animated(let lhsCourseid, let lhsCommentid, let lhsParentcomment, let lhsThreadstatesubject, let lhsIsblackedout, let lhsAnimated), .m_showComments__courseID_courseIDcommentID_commentIDparentComment_parentCommentthreadStateSubject_threadStateSubjectisBlackedOut_isBlackedOutanimated_animated(let rhsCourseid, let rhsCommentid, let rhsParentcomment, let rhsThreadstatesubject, let rhsIsblackedout, let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCommentid, rhs: rhsCommentid, with: matcher), lhsCommentid, rhsCommentid, "commentID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParentcomment, rhs: rhsParentcomment, with: matcher), lhsParentcomment, rhsParentcomment, "parentComment")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsThreadstatesubject, rhs: rhsThreadstatesubject, with: matcher), lhsThreadstatesubject, rhsThreadstatesubject, "threadStateSubject")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIsblackedout, rhs: rhsIsblackedout, with: matcher), lhsIsblackedout, rhsIsblackedout, "isBlackedOut")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_createNewThread__courseID_courseIDselectedTopic_selectedTopiconPostCreated_onPostCreated(let lhsCourseid, let lhsSelectedtopic, let lhsOnpostcreated), .m_createNewThread__courseID_courseIDselectedTopic_selectedTopiconPostCreated_onPostCreated(let rhsCourseid, let rhsSelectedtopic, let rhsOnpostcreated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSelectedtopic, rhs: rhsSelectedtopic, with: matcher), lhsSelectedtopic, rhsSelectedtopic, "selectedTopic")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnpostcreated, rhs: rhsOnpostcreated, with: matcher), lhsOnpostcreated, rhsOnpostcreated, "onPostCreated")) - return Matcher.ComparisonResult(results) - - case (.m_backToRoot__animated_animated(let lhsAnimated), .m_backToRoot__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_back__animated_animated(let lhsAnimated), .m_back__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_backWithFade, .m_backWithFade): return .match - - case (.m_dismiss__animated_animated(let lhsAnimated), .m_dismiss__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_removeLastView__controllers_controllers(let lhsControllers), .m_removeLastView__controllers_controllers(let rhsControllers)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsControllers, rhs: rhsControllers, with: matcher), lhsControllers, rhsControllers, "controllers")) - return Matcher.ComparisonResult(results) - - case (.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let lhsSourcescreen, let lhsPostlogindata), .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let rhsSourcescreen, let rhsPostlogindata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPostlogindata, rhs: rhsPostlogindata, with: matcher), lhsPostlogindata, rhsPostlogindata, "postLoginData")) - return Matcher.ComparisonResult(results) - - case (.m_showStartupScreen, .m_showStartupScreen): return .match - - case (.m_showLoginScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showLoginScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showRegisterScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showRegisterScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showForgotPasswordScreen, .m_showForgotPasswordScreen): return .match - - case (.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let lhsSearchquery, let lhsSourcescreen), .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let rhsSearchquery, let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchquery, rhs: rhsSearchquery, with: matcher), lhsSearchquery, rhsSearchquery, "searchQuery")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showWebBrowser__title_titleurl_url(let lhsTitle, let lhsUrl), .m_showWebBrowser__title_titleurl_url(let rhsTitle, let rhsUrl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - return Matcher.ComparisonResult(results) - - case (.m_showSSOWebBrowser__title_title(let lhsTitle), .m_showSSOWebBrowser__title_title(let rhsTitle)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let lhsAlerttitle, let lhsAlertmessage, let lhsPositiveaction, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsType), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let rhsAlerttitle, let rhsAlertmessage, let rhsPositiveaction, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPositiveaction, rhs: rhsPositiveaction, with: matcher), lhsPositiveaction, rhsPositiveaction, "positiveAction")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let lhsAlerttitle, let lhsAlertmessage, let lhsNextsectionname, let lhsAction, let lhsImage, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsNextsectiontapped), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let rhsAlerttitle, let rhsAlertmessage, let rhsNextsectionname, let rhsAction, let rhsImage, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsNextsectiontapped)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectionname, rhs: rhsNextsectionname, with: matcher), lhsNextsectionname, rhsNextsectionname, "nextSectionName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsImage, rhs: rhsImage, with: matcher), lhsImage, rhsImage, "image")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectiontapped, rhs: rhsNextsectiontapped, with: matcher), lhsNextsectiontapped, rhsNextsectiontapped, "nextSectionTapped")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let lhsTransitionstyle, let lhsView, let lhsCompletion), .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let rhsTransitionstyle, let rhsView, let rhsCompletion)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsView, rhs: rhsView, with: matcher), lhsView, rhsView, "view")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCompletion, rhs: rhsCompletion, with: matcher), lhsCompletion, rhsCompletion, "completion")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let lhsTransitionstyle, let lhsAnimated, let lhsContent), .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let rhsTransitionstyle, let rhsAnimated, let rhsContent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsContent, rhs: rhsContent, with: matcher), lhsContent, rhsContent, "content")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_showUserDetails__username_username(p0): return p0.intValue - case let .m_showThreads__courseID_courseIDtopics_topicstitle_titletype_typeisBlackedOut_isBlackedOutanimated_animated(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_showThread__thread_threadpostStateSubject_postStateSubjectisBlackedOut_isBlackedOutanimated_animated(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_showDiscussionsSearch__courseID_courseIDisBlackedOut_isBlackedOut(p0, p1): return p0.intValue + p1.intValue - case let .m_showComments__courseID_courseIDcommentID_commentIDparentComment_parentCommentthreadStateSubject_threadStateSubjectisBlackedOut_isBlackedOutanimated_animated(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_createNewThread__courseID_courseIDselectedTopic_selectedTopiconPostCreated_onPostCreated(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_backToRoot__animated_animated(p0): return p0.intValue - case let .m_back__animated_animated(p0): return p0.intValue - case .m_backWithFade: return 0 - case let .m_dismiss__animated_animated(p0): return p0.intValue - case let .m_removeLastView__controllers_controllers(p0): return p0.intValue - case let .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(p0, p1): return p0.intValue + p1.intValue - case .m_showStartupScreen: return 0 - case let .m_showLoginScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case let .m_showRegisterScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case .m_showForgotPasswordScreen: return 0 - case let .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(p0, p1): return p0.intValue + p1.intValue - case let .m_showWebBrowser__title_titleurl_url(p0, p1): return p0.intValue + p1.intValue - case let .m_showSSOWebBrowser__title_title(p0): return p0.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(p0, p1, p2, p3, p4, p5, p6, p7): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue + p7.intValue - case let .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_showUserDetails__username_username: return ".showUserDetails(username:)" - case .m_showThreads__courseID_courseIDtopics_topicstitle_titletype_typeisBlackedOut_isBlackedOutanimated_animated: return ".showThreads(courseID:topics:title:type:isBlackedOut:animated:)" - case .m_showThread__thread_threadpostStateSubject_postStateSubjectisBlackedOut_isBlackedOutanimated_animated: return ".showThread(thread:postStateSubject:isBlackedOut:animated:)" - case .m_showDiscussionsSearch__courseID_courseIDisBlackedOut_isBlackedOut: return ".showDiscussionsSearch(courseID:isBlackedOut:)" - case .m_showComments__courseID_courseIDcommentID_commentIDparentComment_parentCommentthreadStateSubject_threadStateSubjectisBlackedOut_isBlackedOutanimated_animated: return ".showComments(courseID:commentID:parentComment:threadStateSubject:isBlackedOut:animated:)" - case .m_createNewThread__courseID_courseIDselectedTopic_selectedTopiconPostCreated_onPostCreated: return ".createNewThread(courseID:selectedTopic:onPostCreated:)" - case .m_backToRoot__animated_animated: return ".backToRoot(animated:)" - case .m_back__animated_animated: return ".back(animated:)" - case .m_backWithFade: return ".backWithFade()" - case .m_dismiss__animated_animated: return ".dismiss(animated:)" - case .m_removeLastView__controllers_controllers: return ".removeLastView(controllers:)" - case .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData: return ".showMainOrWhatsNewScreen(sourceScreen:postLoginData:)" - case .m_showStartupScreen: return ".showStartupScreen()" - case .m_showLoginScreen__sourceScreen_sourceScreen: return ".showLoginScreen(sourceScreen:)" - case .m_showRegisterScreen__sourceScreen_sourceScreen: return ".showRegisterScreen(sourceScreen:)" - case .m_showForgotPasswordScreen: return ".showForgotPasswordScreen()" - case .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen: return ".showDiscoveryScreen(searchQuery:sourceScreen:)" - case .m_showWebBrowser__title_titleurl_url: return ".showWebBrowser(title:url:)" - case .m_showSSOWebBrowser__title_title: return ".showSSOWebBrowser(title:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type: return ".presentAlert(alertTitle:alertMessage:positiveAction:onCloseTapped:firstButtonTapped:type:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped: return ".presentAlert(alertTitle:alertMessage:nextSectionName:action:image:onCloseTapped:firstButtonTapped:nextSectionTapped:)" - case .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion: return ".presentView(transitionStyle:view:completion:)" - case .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content: return ".presentView(transitionStyle:animated:content:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func showUserDetails(username: Parameter) -> Verify { return Verify(method: .m_showUserDetails__username_username(`username`))} - public static func showThreads(courseID: Parameter, topics: Parameter, title: Parameter, type: Parameter, isBlackedOut: Parameter, animated: Parameter) -> Verify { return Verify(method: .m_showThreads__courseID_courseIDtopics_topicstitle_titletype_typeisBlackedOut_isBlackedOutanimated_animated(`courseID`, `topics`, `title`, `type`, `isBlackedOut`, `animated`))} - public static func showThread(thread: Parameter, postStateSubject: Parameter>, isBlackedOut: Parameter, animated: Parameter) -> Verify { return Verify(method: .m_showThread__thread_threadpostStateSubject_postStateSubjectisBlackedOut_isBlackedOutanimated_animated(`thread`, `postStateSubject`, `isBlackedOut`, `animated`))} - public static func showDiscussionsSearch(courseID: Parameter, isBlackedOut: Parameter) -> Verify { return Verify(method: .m_showDiscussionsSearch__courseID_courseIDisBlackedOut_isBlackedOut(`courseID`, `isBlackedOut`))} - public static func showComments(courseID: Parameter, commentID: Parameter, parentComment: Parameter, threadStateSubject: Parameter>, isBlackedOut: Parameter, animated: Parameter) -> Verify { return Verify(method: .m_showComments__courseID_courseIDcommentID_commentIDparentComment_parentCommentthreadStateSubject_threadStateSubjectisBlackedOut_isBlackedOutanimated_animated(`courseID`, `commentID`, `parentComment`, `threadStateSubject`, `isBlackedOut`, `animated`))} - public static func createNewThread(courseID: Parameter, selectedTopic: Parameter, onPostCreated: Parameter<() -> Void>) -> Verify { return Verify(method: .m_createNewThread__courseID_courseIDselectedTopic_selectedTopiconPostCreated_onPostCreated(`courseID`, `selectedTopic`, `onPostCreated`))} - public static func backToRoot(animated: Parameter) -> Verify { return Verify(method: .m_backToRoot__animated_animated(`animated`))} - public static func back(animated: Parameter) -> Verify { return Verify(method: .m_back__animated_animated(`animated`))} - public static func backWithFade() -> Verify { return Verify(method: .m_backWithFade)} - public static func dismiss(animated: Parameter) -> Verify { return Verify(method: .m_dismiss__animated_animated(`animated`))} - public static func removeLastView(controllers: Parameter) -> Verify { return Verify(method: .m_removeLastView__controllers_controllers(`controllers`))} - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter) -> Verify { return Verify(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`))} - public static func showStartupScreen() -> Verify { return Verify(method: .m_showStartupScreen)} - public static func showLoginScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showRegisterScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showForgotPasswordScreen() -> Verify { return Verify(method: .m_showForgotPasswordScreen)} - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter) -> Verify { return Verify(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`))} - public static func showWebBrowser(title: Parameter, url: Parameter) -> Verify { return Verify(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`))} - public static func showSSOWebBrowser(title: Parameter) -> Verify { return Verify(method: .m_showSSOWebBrowser__title_title(`title`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`))} - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`))} - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func showUserDetails(username: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showUserDetails__username_username(`username`), performs: perform) - } - public static func showThreads(courseID: Parameter, topics: Parameter, title: Parameter, type: Parameter, isBlackedOut: Parameter, animated: Parameter, perform: @escaping (String, Topics, String, ThreadType, Bool, Bool) -> Void) -> Perform { - return Perform(method: .m_showThreads__courseID_courseIDtopics_topicstitle_titletype_typeisBlackedOut_isBlackedOutanimated_animated(`courseID`, `topics`, `title`, `type`, `isBlackedOut`, `animated`), performs: perform) - } - public static func showThread(thread: Parameter, postStateSubject: Parameter>, isBlackedOut: Parameter, animated: Parameter, perform: @escaping (UserThread, CurrentValueSubject, Bool, Bool) -> Void) -> Perform { - return Perform(method: .m_showThread__thread_threadpostStateSubject_postStateSubjectisBlackedOut_isBlackedOutanimated_animated(`thread`, `postStateSubject`, `isBlackedOut`, `animated`), performs: perform) - } - public static func showDiscussionsSearch(courseID: Parameter, isBlackedOut: Parameter, perform: @escaping (String, Bool) -> Void) -> Perform { - return Perform(method: .m_showDiscussionsSearch__courseID_courseIDisBlackedOut_isBlackedOut(`courseID`, `isBlackedOut`), performs: perform) - } - public static func showComments(courseID: Parameter, commentID: Parameter, parentComment: Parameter, threadStateSubject: Parameter>, isBlackedOut: Parameter, animated: Parameter, perform: @escaping (String, String, Post, CurrentValueSubject, Bool, Bool) -> Void) -> Perform { - return Perform(method: .m_showComments__courseID_courseIDcommentID_commentIDparentComment_parentCommentthreadStateSubject_threadStateSubjectisBlackedOut_isBlackedOutanimated_animated(`courseID`, `commentID`, `parentComment`, `threadStateSubject`, `isBlackedOut`, `animated`), performs: perform) - } - public static func createNewThread(courseID: Parameter, selectedTopic: Parameter, onPostCreated: Parameter<() -> Void>, perform: @escaping (String, String, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_createNewThread__courseID_courseIDselectedTopic_selectedTopiconPostCreated_onPostCreated(`courseID`, `selectedTopic`, `onPostCreated`), performs: perform) - } - public static func backToRoot(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_backToRoot__animated_animated(`animated`), performs: perform) - } - public static func back(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_back__animated_animated(`animated`), performs: perform) - } - public static func backWithFade(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_backWithFade, performs: perform) - } - public static func dismiss(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_dismiss__animated_animated(`animated`), performs: perform) - } - public static func removeLastView(controllers: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_removeLastView__controllers_controllers(`controllers`), performs: perform) - } - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter, perform: @escaping (LogistrationSourceScreen, PostLoginData?) -> Void) -> Perform { - return Perform(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`), performs: perform) - } - public static func showStartupScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showStartupScreen, performs: perform) - } - public static func showLoginScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showRegisterScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showForgotPasswordScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showForgotPasswordScreen, performs: perform) - } - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter, perform: @escaping (String?, LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`), performs: perform) - } - public static func showWebBrowser(title: Parameter, url: Parameter, perform: @escaping (String, URL) -> Void) -> Perform { - return Perform(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`), performs: perform) - } - public static func showSSOWebBrowser(title: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showSSOWebBrowser__title_title(`title`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter, perform: @escaping (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>, perform: @escaping (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>, perform: @escaping (UIModalTransitionStyle, any View, (() -> Void)?) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>, perform: @escaping (UIModalTransitionStyle, Bool, () -> any View) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DownloadManagerProtocol - -open class DownloadManagerProtocolMock: DownloadManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCurrentDownloadTask() -> DownloadDataTask? { - addInvocation(.m_getCurrentDownloadTask) - let perform = methodPerformValue(.m_getCurrentDownloadTask) as? () -> Void - perform?() - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_getCurrentDownloadTask).casted() - } catch { - // do nothing - } - return __value - } - - open func eventPublisher() -> AnyPublisher { - addInvocation(.m_eventPublisher) - let perform = methodPerformValue(.m_eventPublisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_eventPublisher).casted() - } catch { - onFatalFailure("Stub return value not specified for eventPublisher(). Use given") - Failure("Stub return value not specified for eventPublisher(). Use given") - } - return __value - } - - open func addToDownloadQueue(blocks: [CourseBlock]) throws { - addInvocation(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - do { - _ = try methodReturnValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getDownloadTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasks) - let perform = methodPerformValue(.m_getDownloadTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasks(). Use given") - Failure("Stub return value not specified for getDownloadTasks(). Use given") - } - return __value - } - - open func getDownloadTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func cancelDownloading(courseId: String, blocks: [CourseBlock]) throws { - addInvocation(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) as? (String, [CourseBlock]) -> Void - perform?(`courseId`, `blocks`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(task: DownloadDataTask) throws { - addInvocation(.m_cancelDownloading__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_cancelDownloading__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - do { - _ = try methodReturnValue(.m_cancelDownloading__task_task(Parameter.value(`task`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(courseId: String) throws { - addInvocation(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelAllDownloading() throws { - addInvocation(.m_cancelAllDownloading) - let perform = methodPerformValue(.m_cancelAllDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_cancelAllDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func deleteAll() { - addInvocation(.m_deleteAll) - let perform = methodPerformValue(.m_deleteAll) as? () -> Void - perform?() - } - - open func fileUrl(for blockId: String) -> URL? { - addInvocation(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: URL? = nil - do { - __value = try methodReturnValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func resumeDownloading() throws { - addInvocation(.m_resumeDownloading) - let perform = methodPerformValue(.m_resumeDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_resumeDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func isLargeVideosSize(blocks: [CourseBlock]) -> Bool { - addInvocation(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - Failure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - } - return __value - } - - open func removeAppSupportDirectoryUnusedContent() { - addInvocation(.m_removeAppSupportDirectoryUnusedContent) - let perform = methodPerformValue(.m_removeAppSupportDirectoryUnusedContent) as? () -> Void - perform?() - } - - open func delete(blocks: [CourseBlock], courseId: String) { - addInvocation(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) as? ([CourseBlock], String) -> Void - perform?(`blocks`, `courseId`) - } - - open func downloadTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getFreeDiskSpace() -> Int? { - addInvocation(.m_getFreeDiskSpace) - let perform = methodPerformValue(.m_getFreeDiskSpace) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getFreeDiskSpace).casted() - } catch { - // do nothing - } - return __value - } - - - fileprivate enum MethodType { - case m_getCurrentDownloadTask - case m_eventPublisher - case m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>) - case m_getDownloadTasks - case m_getDownloadTasksForCourse__courseId(Parameter) - case m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter, Parameter<[CourseBlock]>) - case m_cancelDownloading__task_task(Parameter) - case m_cancelDownloading__courseId_courseId(Parameter) - case m_cancelAllDownloading - case m_deleteAll - case m_fileUrl__for_blockId(Parameter) - case m_resumeDownloading - case m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>) - case m_removeAppSupportDirectoryUnusedContent - case m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>, Parameter) - case m_downloadTask__for_blockId(Parameter) - case m_getFreeDiskSpace - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCurrentDownloadTask, .m_getCurrentDownloadTask): return .match - - case (.m_eventPublisher, .m_eventPublisher): return .match - - case (.m_addToDownloadQueue__blocks_blocks(let lhsBlocks), .m_addToDownloadQueue__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadTasks, .m_getDownloadTasks): return .match - - case (.m_getDownloadTasksForCourse__courseId(let lhsCourseid), .m_getDownloadTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseIdblocks_blocks(let lhsCourseid, let lhsBlocks), .m_cancelDownloading__courseId_courseIdblocks_blocks(let rhsCourseid, let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__task_task(let lhsTask), .m_cancelDownloading__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseId(let lhsCourseid), .m_cancelDownloading__courseId_courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelAllDownloading, .m_cancelAllDownloading): return .match - - case (.m_deleteAll, .m_deleteAll): return .match - - case (.m_fileUrl__for_blockId(let lhsBlockid), .m_fileUrl__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_resumeDownloading, .m_resumeDownloading): return .match - - case (.m_isLargeVideosSize__blocks_blocks(let lhsBlocks), .m_isLargeVideosSize__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_removeAppSupportDirectoryUnusedContent, .m_removeAppSupportDirectoryUnusedContent): return .match - - case (.m_delete__blocks_blockscourseId_courseId(let lhsBlocks, let lhsCourseid), .m_delete__blocks_blockscourseId_courseId(let rhsBlocks, let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_downloadTask__for_blockId(let lhsBlockid), .m_downloadTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getFreeDiskSpace, .m_getFreeDiskSpace): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_getCurrentDownloadTask: return 0 - case .m_eventPublisher: return 0 - case let .m_addToDownloadQueue__blocks_blocks(p0): return p0.intValue - case .m_getDownloadTasks: return 0 - case let .m_getDownloadTasksForCourse__courseId(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseIdblocks_blocks(p0, p1): return p0.intValue + p1.intValue - case let .m_cancelDownloading__task_task(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseId(p0): return p0.intValue - case .m_cancelAllDownloading: return 0 - case .m_deleteAll: return 0 - case let .m_fileUrl__for_blockId(p0): return p0.intValue - case .m_resumeDownloading: return 0 - case let .m_isLargeVideosSize__blocks_blocks(p0): return p0.intValue - case .m_removeAppSupportDirectoryUnusedContent: return 0 - case let .m_delete__blocks_blockscourseId_courseId(p0, p1): return p0.intValue + p1.intValue - case let .m_downloadTask__for_blockId(p0): return p0.intValue - case .m_getFreeDiskSpace: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_getCurrentDownloadTask: return ".getCurrentDownloadTask()" - case .m_eventPublisher: return ".eventPublisher()" - case .m_addToDownloadQueue__blocks_blocks: return ".addToDownloadQueue(blocks:)" - case .m_getDownloadTasks: return ".getDownloadTasks()" - case .m_getDownloadTasksForCourse__courseId: return ".getDownloadTasksForCourse(_:)" - case .m_cancelDownloading__courseId_courseIdblocks_blocks: return ".cancelDownloading(courseId:blocks:)" - case .m_cancelDownloading__task_task: return ".cancelDownloading(task:)" - case .m_cancelDownloading__courseId_courseId: return ".cancelDownloading(courseId:)" - case .m_cancelAllDownloading: return ".cancelAllDownloading()" - case .m_deleteAll: return ".deleteAll()" - case .m_fileUrl__for_blockId: return ".fileUrl(for:)" - case .m_resumeDownloading: return ".resumeDownloading()" - case .m_isLargeVideosSize__blocks_blocks: return ".isLargeVideosSize(blocks:)" - case .m_removeAppSupportDirectoryUnusedContent: return ".removeAppSupportDirectoryUnusedContent()" - case .m_delete__blocks_blockscourseId_courseId: return ".delete(blocks:courseId:)" - case .m_downloadTask__for_blockId: return ".downloadTask(for:)" - case .m_getFreeDiskSpace: return ".getFreeDiskSpace()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCurrentDownloadTask(willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func eventPublisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func fileUrl(for blockId: Parameter, willReturn: URL?...) -> MethodStub { - return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getFreeDiskSpace(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCurrentDownloadTask(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func eventPublisher(willProduce: (Stubber>) -> Void) -> MethodStub { - let willReturn: [AnyPublisher] = [] - let given: Given = { return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - public static func getDownloadTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func fileUrl(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [URL?] = [] - let given: Given = { return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (URL?).self) - willProduce(stubber) - return given - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func downloadTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getFreeDiskSpace(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(task: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(task: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelAllDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelAllDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func resumeDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resumeDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCurrentDownloadTask() -> Verify { return Verify(method: .m_getCurrentDownloadTask)} - public static func eventPublisher() -> Verify { return Verify(method: .m_eventPublisher)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocks(`blocks`))} - public static func getDownloadTasks() -> Verify { return Verify(method: .m_getDownloadTasks)} - public static func getDownloadTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadTasksForCourse__courseId(`courseId`))} - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`))} - public static func cancelDownloading(task: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__task_task(`task`))} - public static func cancelDownloading(courseId: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseId(`courseId`))} - public static func cancelAllDownloading() -> Verify { return Verify(method: .m_cancelAllDownloading)} - public static func deleteAll() -> Verify { return Verify(method: .m_deleteAll)} - public static func fileUrl(for blockId: Parameter) -> Verify { return Verify(method: .m_fileUrl__for_blockId(`blockId`))} - public static func resumeDownloading() -> Verify { return Verify(method: .m_resumeDownloading)} - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_isLargeVideosSize__blocks_blocks(`blocks`))} - public static func removeAppSupportDirectoryUnusedContent() -> Verify { return Verify(method: .m_removeAppSupportDirectoryUnusedContent)} - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter) -> Verify { return Verify(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`))} - public static func downloadTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadTask__for_blockId(`blockId`))} - public static func getFreeDiskSpace() -> Verify { return Verify(method: .m_getFreeDiskSpace)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCurrentDownloadTask(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getCurrentDownloadTask, performs: perform) - } - public static func eventPublisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_eventPublisher, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), performs: perform) - } - public static func getDownloadTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadTasks, performs: perform) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, perform: @escaping (String, [CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), performs: perform) - } - public static func cancelDownloading(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__task_task(`task`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseId(`courseId`), performs: perform) - } - public static func cancelAllDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_cancelAllDownloading, performs: perform) - } - public static func deleteAll(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAll, performs: perform) - } - public static func fileUrl(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_fileUrl__for_blockId(`blockId`), performs: perform) - } - public static func resumeDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_resumeDownloading, performs: perform) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), performs: perform) - } - public static func removeAppSupportDirectoryUnusedContent(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeAppSupportDirectoryUnusedContent, performs: perform) - } - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter, perform: @escaping ([CourseBlock], String) -> Void) -> Perform { - return Perform(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`), performs: perform) - } - public static func downloadTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadTask__for_blockId(`blockId`), performs: perform) - } - public static func getFreeDiskSpace(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getFreeDiskSpace, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - OfflineSyncInteractorProtocol - -open class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func submitOfflineProgress(courseID: String, blockID: String, data: String) throws -> Bool { - addInvocation(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) - let perform = methodPerformValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) as? (String, String, String) -> Void - perform?(`courseID`, `blockID`, `data`) - var __value: Bool - do { - __value = try methodReturnValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - Failure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter, Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let lhsCourseid, let lhsBlockid, let lhsData), .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let rhsCourseid, let rhsBlockid, let rhsData)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsData, rhs: rhsData, with: matcher), lhsData, rhsData, "data")) - return Matcher.ComparisonResult(results) - } - } - - func intValue() -> Int { - switch self { - case let .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data: return ".submitOfflineProgress(courseID:blockID:data:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter) -> Verify { return Verify(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - diff --git a/Discussion/DiscussionTests/Generated/DiscussionMocks.generated.swift b/Discussion/DiscussionTests/Generated/DiscussionMocks.generated.swift new file mode 100644 index 000000000..6c5a824f4 --- /dev/null +++ b/Discussion/DiscussionTests/Generated/DiscussionMocks.generated.swift @@ -0,0 +1,2689 @@ +/// +/// @Generated by Mockolo +/// + + + +import Alamofire +import Combine +@testable import Core +import CoreData +@testable import Discussion +import Foundation +import OEXFoundation +import SwiftUI +import ZipArchive + + +public final class ConfigProtocolMock: ConfigProtocol, @unchecked Sendable { + public init() { } + public init(baseURL: URL = URL(fileURLWithPath: ""), baseSSOURL: URL = URL(fileURLWithPath: ""), ssoFinishedURL: URL = URL(fileURLWithPath: ""), ssoButtonTitle: [String: Any] = [String: Any](), oAuthClientId: String = "", tokenType: TokenType, feedbackEmail: String = "", appStoreLink: String = "", faq: URL? = nil, platformName: String = "", agreement: AgreementConfig, firebase: FirebaseConfig, facebook: FacebookConfig, microsoft: MicrosoftConfig, google: GoogleConfig, appleSignIn: AppleSignInConfig, features: FeaturesConfig, theme: ThemeConfig, uiComponents: UIComponentsConfig, discovery: DiscoveryConfig, dashboard: DashboardConfig, braze: BrazeConfig, branch: BranchConfig, program: DiscoveryConfig, experimentalFeatures: ExperimentalFeaturesConfig, URIScheme: String = "") { + self.baseURL = baseURL + self.baseSSOURL = baseSSOURL + self.ssoFinishedURL = ssoFinishedURL + self.ssoButtonTitle = ssoButtonTitle + self.oAuthClientId = oAuthClientId + self._tokenType = tokenType + self.feedbackEmail = feedbackEmail + self.appStoreLink = appStoreLink + self.faq = faq + self.platformName = platformName + self._agreement = agreement + self._firebase = firebase + self._facebook = facebook + self._microsoft = microsoft + self._google = google + self._appleSignIn = appleSignIn + self._features = features + self._theme = theme + self._uiComponents = uiComponents + self._discovery = discovery + self._dashboard = dashboard + self._braze = braze + self._branch = branch + self._program = program + self._experimentalFeatures = experimentalFeatures + self.URIScheme = URIScheme + } + + + + public var baseURL: URL = URL(fileURLWithPath: "") + + + public var baseSSOURL: URL = URL(fileURLWithPath: "") + + + public var ssoFinishedURL: URL = URL(fileURLWithPath: "") + + + public var ssoButtonTitle: [String: Any] = [String: Any]() + + + public var oAuthClientId: String = "" + + + private var _tokenType: TokenType! + public var tokenType: TokenType { + get { return _tokenType } + set { _tokenType = newValue } + } + + + public var feedbackEmail: String = "" + + + public var appStoreLink: String = "" + + + public var faq: URL? = nil + + + public var platformName: String = "" + + + private var _agreement: AgreementConfig! + public var agreement: AgreementConfig { + get { return _agreement } + set { _agreement = newValue } + } + + + private var _firebase: FirebaseConfig! + public var firebase: FirebaseConfig { + get { return _firebase } + set { _firebase = newValue } + } + + + private var _facebook: FacebookConfig! + public var facebook: FacebookConfig { + get { return _facebook } + set { _facebook = newValue } + } + + + private var _microsoft: MicrosoftConfig! + public var microsoft: MicrosoftConfig { + get { return _microsoft } + set { _microsoft = newValue } + } + + + private var _google: GoogleConfig! + public var google: GoogleConfig { + get { return _google } + set { _google = newValue } + } + + + private var _appleSignIn: AppleSignInConfig! + public var appleSignIn: AppleSignInConfig { + get { return _appleSignIn } + set { _appleSignIn = newValue } + } + + + private var _features: FeaturesConfig! + public var features: FeaturesConfig { + get { return _features } + set { _features = newValue } + } + + + private var _theme: ThemeConfig! + public var theme: ThemeConfig { + get { return _theme } + set { _theme = newValue } + } + + + private var _uiComponents: UIComponentsConfig! + public var uiComponents: UIComponentsConfig { + get { return _uiComponents } + set { _uiComponents = newValue } + } + + + private var _discovery: DiscoveryConfig! + public var discovery: DiscoveryConfig { + get { return _discovery } + set { _discovery = newValue } + } + + + private var _dashboard: DashboardConfig! + public var dashboard: DashboardConfig { + get { return _dashboard } + set { _dashboard = newValue } + } + + + private var _braze: BrazeConfig! + public var braze: BrazeConfig { + get { return _braze } + set { _braze = newValue } + } + + + private var _branch: BranchConfig! + public var branch: BranchConfig { + get { return _branch } + set { _branch = newValue } + } + + + private var _program: DiscoveryConfig! + public var program: DiscoveryConfig { + get { return _program } + set { _program = newValue } + } + + + private var _experimentalFeatures: ExperimentalFeaturesConfig! + public var experimentalFeatures: ExperimentalFeaturesConfig { + get { return _experimentalFeatures } + set { _experimentalFeatures = newValue } + } + + + public var URIScheme: String = "" +} + +public final class CoreAnalyticsMock: CoreAnalytics { + public init() { } + + + public private(set) var trackEventCallCount = 0 + public var trackEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackEventCallCount += 1 + if let trackEventHandler = trackEventHandler { + trackEventHandler(event, parameters) + } + + } + + public private(set) var trackEventBiValueCallCount = 0 + public var trackEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackEventBiValueCallCount += 1 + if let trackEventBiValueHandler = trackEventBiValueHandler { + trackEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var trackScreenEventCallCount = 0 + public var trackScreenEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackScreenEventCallCount += 1 + if let trackScreenEventHandler = trackScreenEventHandler { + trackScreenEventHandler(event, parameters) + } + + } + + public private(set) var trackScreenEventBiValueCallCount = 0 + public var trackScreenEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackScreenEventBiValueCallCount += 1 + if let trackScreenEventBiValueHandler = trackScreenEventBiValueHandler { + trackScreenEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var appreviewCallCount = 0 + public var appreviewHandler: ((AnalyticsEvent, EventBIValue, String?, Int?) -> ())? + public func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { + appreviewCallCount += 1 + if let appreviewHandler = appreviewHandler { + appreviewHandler(event, biValue, action, rating) + } + + } + + public private(set) var videoQualityChangedCallCount = 0 + public var videoQualityChangedHandler: ((AnalyticsEvent, EventBIValue, String, String) -> ())? + public func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { + videoQualityChangedCallCount += 1 + if let videoQualityChangedHandler = videoQualityChangedHandler { + videoQualityChangedHandler(event, bivalue, value, oldValue) + } + + } +} + +public final class CoreStorageMock: CoreStorage, @unchecked Sendable { + public init() { } + public init(accessToken: String? = nil, refreshToken: String? = nil, pushToken: String? = nil, appleSignFullName: String? = nil, appleSignEmail: String? = nil, cookiesDate: Date? = nil, reviewLastShownVersion: String? = nil, lastReviewDate: Date? = nil, user: DataLayer.User? = nil, userSettings: UserSettings? = nil, resetAppSupportDirectoryUserData: Bool? = nil, useRelativeDates: Bool = false, lastUsedSocialAuth: String? = nil, latestAvailableAppVersion: String? = nil, updateAppRequired: Bool = false) { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.pushToken = pushToken + self.appleSignFullName = appleSignFullName + self.appleSignEmail = appleSignEmail + self.cookiesDate = cookiesDate + self.reviewLastShownVersion = reviewLastShownVersion + self.lastReviewDate = lastReviewDate + self.user = user + self.userSettings = userSettings + self.resetAppSupportDirectoryUserData = resetAppSupportDirectoryUserData + self.useRelativeDates = useRelativeDates + self.lastUsedSocialAuth = lastUsedSocialAuth + self.latestAvailableAppVersion = latestAvailableAppVersion + self.updateAppRequired = updateAppRequired + } + + + public private(set) var accessTokenSetCallCount = 0 + public var accessToken: String? = nil { didSet { accessTokenSetCallCount += 1 } } + + public private(set) var refreshTokenSetCallCount = 0 + public var refreshToken: String? = nil { didSet { refreshTokenSetCallCount += 1 } } + + public private(set) var pushTokenSetCallCount = 0 + public var pushToken: String? = nil { didSet { pushTokenSetCallCount += 1 } } + + public private(set) var appleSignFullNameSetCallCount = 0 + public var appleSignFullName: String? = nil { didSet { appleSignFullNameSetCallCount += 1 } } + + public private(set) var appleSignEmailSetCallCount = 0 + public var appleSignEmail: String? = nil { didSet { appleSignEmailSetCallCount += 1 } } + + public private(set) var cookiesDateSetCallCount = 0 + public var cookiesDate: Date? = nil { didSet { cookiesDateSetCallCount += 1 } } + + public private(set) var reviewLastShownVersionSetCallCount = 0 + public var reviewLastShownVersion: String? = nil { didSet { reviewLastShownVersionSetCallCount += 1 } } + + public private(set) var lastReviewDateSetCallCount = 0 + public var lastReviewDate: Date? = nil { didSet { lastReviewDateSetCallCount += 1 } } + + public private(set) var userSetCallCount = 0 + public var user: DataLayer.User? = nil { didSet { userSetCallCount += 1 } } + + public private(set) var userSettingsSetCallCount = 0 + public var userSettings: UserSettings? = nil { didSet { userSettingsSetCallCount += 1 } } + + public private(set) var resetAppSupportDirectoryUserDataSetCallCount = 0 + public var resetAppSupportDirectoryUserData: Bool? = nil { didSet { resetAppSupportDirectoryUserDataSetCallCount += 1 } } + + public private(set) var useRelativeDatesSetCallCount = 0 + public var useRelativeDates: Bool = false { didSet { useRelativeDatesSetCallCount += 1 } } + + public private(set) var lastUsedSocialAuthSetCallCount = 0 + public var lastUsedSocialAuth: String? = nil { didSet { lastUsedSocialAuthSetCallCount += 1 } } + + public private(set) var latestAvailableAppVersionSetCallCount = 0 + public var latestAvailableAppVersion: String? = nil { didSet { latestAvailableAppVersionSetCallCount += 1 } } + + public private(set) var updateAppRequiredSetCallCount = 0 + public var updateAppRequired: Bool = false { didSet { updateAppRequiredSetCallCount += 1 } } + + private let clearState = MockoloMutex(MockoloHandlerState ()>()) + public var clearCallCount: Int { + return clearState.withLock(\.callCount) + } + public var clearHandler: (@Sendable () -> ())? { + get { clearState.withLock(\.handler) } + set { clearState.withLock { $0.handler = newValue } } + } + public func clear() { + let clearHandler = clearState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearHandler = clearHandler { + clearHandler() + } + + } +} + +public final class AuthInteractorProtocolMock: AuthInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let loginState = MockoloMutex(MockoloHandlerState User>()) + public var loginCallCount: Int { + return loginState.withLock(\.callCount) + } + public var loginHandler: (@Sendable (String, String) async throws -> User)? { + get { loginState.withLock(\.handler) } + set { loginState.withLock { $0.handler = newValue } } + } + public func login(username: String, password: String) async throws -> User { + let loginHandler = loginState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginHandler = loginHandler { + return try await loginHandler(username, password) + } + fatalError("loginHandler returns can't have a default value thus its handler must be set") + } + + private let loginExternalTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginExternalTokenCallCount: Int { + return loginExternalTokenState.withLock(\.callCount) + } + public var loginExternalTokenHandler: (@Sendable (String, String) async throws -> User)? { + get { loginExternalTokenState.withLock(\.handler) } + set { loginExternalTokenState.withLock { $0.handler = newValue } } + } + public func login(externalToken: String, backend: String) async throws -> User { + let loginExternalTokenHandler = loginExternalTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginExternalTokenHandler = loginExternalTokenHandler { + return try await loginExternalTokenHandler(externalToken, backend) + } + fatalError("loginExternalTokenHandler returns can't have a default value thus its handler must be set") + } + + private let loginSsoTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginSsoTokenCallCount: Int { + return loginSsoTokenState.withLock(\.callCount) + } + public var loginSsoTokenHandler: (@Sendable (String) async throws -> User)? { + get { loginSsoTokenState.withLock(\.handler) } + set { loginSsoTokenState.withLock { $0.handler = newValue } } + } + public func login(ssoToken: String) async throws -> User { + let loginSsoTokenHandler = loginSsoTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginSsoTokenHandler = loginSsoTokenHandler { + return try await loginSsoTokenHandler(ssoToken) + } + fatalError("loginSsoTokenHandler returns can't have a default value thus its handler must be set") + } + + private let resetPasswordState = MockoloMutex(MockoloHandlerState ResetPassword>()) + public var resetPasswordCallCount: Int { + return resetPasswordState.withLock(\.callCount) + } + public var resetPasswordHandler: (@Sendable (String) async throws -> ResetPassword)? { + get { resetPasswordState.withLock(\.handler) } + set { resetPasswordState.withLock { $0.handler = newValue } } + } + public func resetPassword(email: String) async throws -> ResetPassword { + let resetPasswordHandler = resetPasswordState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resetPasswordHandler = resetPasswordHandler { + return try await resetPasswordHandler(email) + } + fatalError("resetPasswordHandler returns can't have a default value thus its handler must be set") + } + + private let getCookiesState = MockoloMutex(MockoloHandlerState ()>()) + public var getCookiesCallCount: Int { + return getCookiesState.withLock(\.callCount) + } + public var getCookiesHandler: (@Sendable (Bool) async throws -> ())? { + get { getCookiesState.withLock(\.handler) } + set { getCookiesState.withLock { $0.handler = newValue } } + } + public func getCookies(force: Bool) async throws { + let getCookiesHandler = getCookiesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCookiesHandler = getCookiesHandler { + try await getCookiesHandler(force) + } + + } + + private let getRegistrationFieldsState = MockoloMutex(MockoloHandlerState [PickerFields]>()) + public var getRegistrationFieldsCallCount: Int { + return getRegistrationFieldsState.withLock(\.callCount) + } + public var getRegistrationFieldsHandler: (@Sendable () async throws -> [PickerFields])? { + get { getRegistrationFieldsState.withLock(\.handler) } + set { getRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func getRegistrationFields() async throws -> [PickerFields] { + let getRegistrationFieldsHandler = getRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getRegistrationFieldsHandler = getRegistrationFieldsHandler { + return try await getRegistrationFieldsHandler() + } + return [PickerFields]() + } + + private let registerUserState = MockoloMutex(MockoloHandlerState User>()) + public var registerUserCallCount: Int { + return registerUserState.withLock(\.callCount) + } + public var registerUserHandler: (@Sendable ([String: String], Bool) async throws -> User)? { + get { registerUserState.withLock(\.handler) } + set { registerUserState.withLock { $0.handler = newValue } } + } + public func registerUser(fields: [String: String], isSocial: Bool) async throws -> User { + let registerUserHandler = registerUserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let registerUserHandler = registerUserHandler { + return try await registerUserHandler(fields, isSocial) + } + fatalError("registerUserHandler returns can't have a default value thus its handler must be set") + } + + private let validateRegistrationFieldsState = MockoloMutex(MockoloHandlerState [String: String]>()) + public var validateRegistrationFieldsCallCount: Int { + return validateRegistrationFieldsState.withLock(\.callCount) + } + public var validateRegistrationFieldsHandler: (@Sendable ([String: String]) async throws -> [String: String])? { + get { validateRegistrationFieldsState.withLock(\.handler) } + set { validateRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func validateRegistrationFields(fields: [String: String]) async throws -> [String: String] { + let validateRegistrationFieldsHandler = validateRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let validateRegistrationFieldsHandler = validateRegistrationFieldsHandler { + return try await validateRegistrationFieldsHandler(fields) + } + return [String: String]() + } +} + +public final class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let submitOfflineProgressState = MockoloMutex(MockoloHandlerState Bool>()) + public var submitOfflineProgressCallCount: Int { + return submitOfflineProgressState.withLock(\.callCount) + } + public var submitOfflineProgressHandler: (@Sendable (String, String, String) async throws -> Bool)? { + get { submitOfflineProgressState.withLock(\.handler) } + set { submitOfflineProgressState.withLock { $0.handler = newValue } } + } + public func submitOfflineProgress(courseID: String, blockID: String, data: String) async throws -> Bool { + let submitOfflineProgressHandler = submitOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let submitOfflineProgressHandler = submitOfflineProgressHandler { + return try await submitOfflineProgressHandler(courseID, blockID, data) + } + return false + } +} + +public final class WebviewCookiesUpdateProtocolMock: WebviewCookiesUpdateProtocol { + public init() { } + public init(authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock(), cookiesReady: Bool = false, updatingCookies: Bool = false, errorMessage: String? = nil) { + self.authInteractor = authInteractor + self.cookiesReady = cookiesReady + self.updatingCookies = updatingCookies + self.errorMessage = errorMessage + } + + + + public var authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock() + + public private(set) var cookiesReadySetCallCount = 0 + public var cookiesReady: Bool = false { didSet { cookiesReadySetCallCount += 1 } } + + public private(set) var updatingCookiesSetCallCount = 0 + public var updatingCookies: Bool = false { didSet { updatingCookiesSetCallCount += 1 } } + + public private(set) var errorMessageSetCallCount = 0 + public var errorMessage: String? = nil { didSet { errorMessageSetCallCount += 1 } } + + public private(set) var updateCookiesCallCount = 0 + public var updateCookiesHandler: ((Bool, Int) async -> ())? + public func updateCookies(force: Bool, retryCount: Int) async { + updateCookiesCallCount += 1 + if let updateCookiesHandler = updateCookiesHandler { + await updateCookiesHandler(force, retryCount) + } + + } +} + +public final class BaseRouterMock: BaseRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class CalendarManagerProtocolMock: CalendarManagerProtocol, @unchecked Sendable { + public init() { } + + + private let createCalendarIfNeededState = MockoloMutex(MockoloHandlerState ()>()) + public var createCalendarIfNeededCallCount: Int { + return createCalendarIfNeededState.withLock(\.callCount) + } + public var createCalendarIfNeededHandler: (@Sendable () -> ())? { + get { createCalendarIfNeededState.withLock(\.handler) } + set { createCalendarIfNeededState.withLock { $0.handler = newValue } } + } + public func createCalendarIfNeeded() { + let createCalendarIfNeededHandler = createCalendarIfNeededState.withLock { state in + state.callCount += 1 + return state.handler + } + if let createCalendarIfNeededHandler = createCalendarIfNeededHandler { + createCalendarIfNeededHandler() + } + + } + + private let filterCoursesBySelectedState = MockoloMutex(MockoloHandlerState [CourseForSync]>()) + public var filterCoursesBySelectedCallCount: Int { + return filterCoursesBySelectedState.withLock(\.callCount) + } + public var filterCoursesBySelectedHandler: (@Sendable ([CourseForSync]) async -> [CourseForSync])? { + get { filterCoursesBySelectedState.withLock(\.handler) } + set { filterCoursesBySelectedState.withLock { $0.handler = newValue } } + } + public func filterCoursesBySelected(fetchedCourses: [CourseForSync]) async -> [CourseForSync] { + let filterCoursesBySelectedHandler = filterCoursesBySelectedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let filterCoursesBySelectedHandler = filterCoursesBySelectedHandler { + return await filterCoursesBySelectedHandler(fetchedCourses) + } + return [CourseForSync]() + } + + private let removeOldCalendarState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOldCalendarCallCount: Int { + return removeOldCalendarState.withLock(\.callCount) + } + public var removeOldCalendarHandler: (@Sendable () -> ())? { + get { removeOldCalendarState.withLock(\.handler) } + set { removeOldCalendarState.withLock { $0.handler = newValue } } + } + public func removeOldCalendar() { + let removeOldCalendarHandler = removeOldCalendarState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOldCalendarHandler = removeOldCalendarHandler { + removeOldCalendarHandler() + } + + } + + private let removeOutdatedEventsState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOutdatedEventsCallCount: Int { + return removeOutdatedEventsState.withLock(\.callCount) + } + public var removeOutdatedEventsHandler: (@Sendable (String) async -> ())? { + get { removeOutdatedEventsState.withLock(\.handler) } + set { removeOutdatedEventsState.withLock { $0.handler = newValue } } + } + public func removeOutdatedEvents(courseID: String) async { + let removeOutdatedEventsHandler = removeOutdatedEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOutdatedEventsHandler = removeOutdatedEventsHandler { + await removeOutdatedEventsHandler(courseID) + } + + } + + private let syncCourseState = MockoloMutex(MockoloHandlerState ()>()) + public var syncCourseCallCount: Int { + return syncCourseState.withLock(\.callCount) + } + public var syncCourseHandler: (@Sendable (String, String, CourseDates) async -> ())? { + get { syncCourseState.withLock(\.handler) } + set { syncCourseState.withLock { $0.handler = newValue } } + } + public func syncCourse(courseID: String, courseName: String, dates: CourseDates) async { + let syncCourseHandler = syncCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let syncCourseHandler = syncCourseHandler { + await syncCourseHandler(courseID, courseName, dates) + } + + } + + private let requestAccessState = MockoloMutex(MockoloHandlerState Bool>()) + public var requestAccessCallCount: Int { + return requestAccessState.withLock(\.callCount) + } + public var requestAccessHandler: (@Sendable () async -> Bool)? { + get { requestAccessState.withLock(\.handler) } + set { requestAccessState.withLock { $0.handler = newValue } } + } + public func requestAccess() async -> Bool { + let requestAccessHandler = requestAccessState.withLock { state in + state.callCount += 1 + return state.handler + } + if let requestAccessHandler = requestAccessHandler { + return await requestAccessHandler() + } + return false + } + + private let courseStatusState = MockoloMutex(MockoloHandlerState SyncStatus>()) + public var courseStatusCallCount: Int { + return courseStatusState.withLock(\.callCount) + } + public var courseStatusHandler: (@Sendable (String) async -> SyncStatus)? { + get { courseStatusState.withLock(\.handler) } + set { courseStatusState.withLock { $0.handler = newValue } } + } + public func courseStatus(courseID: String) async -> SyncStatus { + let courseStatusHandler = courseStatusState.withLock { state in + state.callCount += 1 + return state.handler + } + if let courseStatusHandler = courseStatusHandler { + return await courseStatusHandler(courseID) + } + fatalError("courseStatusHandler returns can't have a default value thus its handler must be set") + } + + private let clearAllDataState = MockoloMutex(MockoloHandlerState ()>()) + public var clearAllDataCallCount: Int { + return clearAllDataState.withLock(\.callCount) + } + public var clearAllDataHandler: (@Sendable (Bool) async -> ())? { + get { clearAllDataState.withLock(\.handler) } + set { clearAllDataState.withLock { $0.handler = newValue } } + } + public func clearAllData(removeCalendar: Bool) async { + let clearAllDataHandler = clearAllDataState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearAllDataHandler = clearAllDataHandler { + await clearAllDataHandler(removeCalendar) + } + + } + + private let isDatesChangedState = MockoloMutex(MockoloHandlerState Bool>()) + public var isDatesChangedCallCount: Int { + return isDatesChangedState.withLock(\.callCount) + } + public var isDatesChangedHandler: (@Sendable (String, String) async -> Bool)? { + get { isDatesChangedState.withLock(\.handler) } + set { isDatesChangedState.withLock { $0.handler = newValue } } + } + public func isDatesChanged(courseID: String, checksum: String) async -> Bool { + let isDatesChangedHandler = isDatesChangedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isDatesChangedHandler = isDatesChangedHandler { + return await isDatesChangedHandler(courseID, checksum) + } + return false + } +} + +public final class DiscussionAnalyticsMock: DiscussionAnalytics { + public init() { } + + + public private(set) var discussionAllPostsClickedCallCount = 0 + public var discussionAllPostsClickedHandler: ((String, String) -> ())? + public func discussionAllPostsClicked(courseId: String, courseName: String) { + discussionAllPostsClickedCallCount += 1 + if let discussionAllPostsClickedHandler = discussionAllPostsClickedHandler { + discussionAllPostsClickedHandler(courseId, courseName) + } + + } + + public private(set) var discussionFollowingClickedCallCount = 0 + public var discussionFollowingClickedHandler: ((String, String) -> ())? + public func discussionFollowingClicked(courseId: String, courseName: String) { + discussionFollowingClickedCallCount += 1 + if let discussionFollowingClickedHandler = discussionFollowingClickedHandler { + discussionFollowingClickedHandler(courseId, courseName) + } + + } + + public private(set) var discussionTopicClickedCallCount = 0 + public var discussionTopicClickedHandler: ((String, String, String, String) -> ())? + public func discussionTopicClicked(courseId: String, courseName: String, topicId: String, topicName: String) { + discussionTopicClickedCallCount += 1 + if let discussionTopicClickedHandler = discussionTopicClickedHandler { + discussionTopicClickedHandler(courseId, courseName, topicId, topicName) + } + + } + + public private(set) var discussionCreateNewPostCallCount = 0 + public var discussionCreateNewPostHandler: ((String, String, String, Bool, String) -> ())? + public func discussionCreateNewPost(courseID: String, topicID: String, postType: String, followPost: Bool, author: String) { + discussionCreateNewPostCallCount += 1 + if let discussionCreateNewPostHandler = discussionCreateNewPostHandler { + discussionCreateNewPostHandler(courseID, topicID, postType, followPost, author) + } + + } + + public private(set) var discussionResponseAddedCallCount = 0 + public var discussionResponseAddedHandler: ((String, String, String, String) -> ())? + public func discussionResponseAdded(courseID: String, threadID: String, responseID: String, author: String) { + discussionResponseAddedCallCount += 1 + if let discussionResponseAddedHandler = discussionResponseAddedHandler { + discussionResponseAddedHandler(courseID, threadID, responseID, author) + } + + } + + public private(set) var discussionCommentAddedCallCount = 0 + public var discussionCommentAddedHandler: ((String, String, String, String, String) -> ())? + public func discussionCommentAdded(courseID: String, threadID: String, responseID: String, commentID: String, author: String) { + discussionCommentAddedCallCount += 1 + if let discussionCommentAddedHandler = discussionCommentAddedHandler { + discussionCommentAddedHandler(courseID, threadID, responseID, commentID, author) + } + + } + + public private(set) var discussionFollowToggleCallCount = 0 + public var discussionFollowToggleHandler: ((String, String, String, Bool) -> ())? + public func discussionFollowToggle(courseID: String, threadID: String, author: String, follow: Bool) { + discussionFollowToggleCallCount += 1 + if let discussionFollowToggleHandler = discussionFollowToggleHandler { + discussionFollowToggleHandler(courseID, threadID, author, follow) + } + + } + + public private(set) var discussionLikeToggleCallCount = 0 + public var discussionLikeToggleHandler: ((String, String, String?, String?, String, String, Bool) -> ())? + public func discussionLikeToggle(courseID: String, threadID: String, responseID: String?, commentID: String?, author: String, discussionType: String, like: Bool) { + discussionLikeToggleCallCount += 1 + if let discussionLikeToggleHandler = discussionLikeToggleHandler { + discussionLikeToggleHandler(courseID, threadID, responseID, commentID, author, discussionType, like) + } + + } + + public private(set) var discussionReportToggleCallCount = 0 + public var discussionReportToggleHandler: ((String, String, String?, String?, String, String, Bool) -> ())? + public func discussionReportToggle(courseID: String, threadID: String, responseID: String?, commentID: String?, author: String, discussionType: String, report: Bool) { + discussionReportToggleCallCount += 1 + if let discussionReportToggleHandler = discussionReportToggleHandler { + discussionReportToggleHandler(courseID, threadID, responseID, commentID, author, discussionType, report) + } + + } +} + +public final class CorePersistenceProtocolMock: CorePersistenceProtocol, @unchecked Sendable { + public init() { } + + + private let setState = MockoloMutex(MockoloHandlerState ()>()) + public var setCallCount: Int { + return setState.withLock(\.callCount) + } + public var setHandler: (@Sendable (Int) -> ())? { + get { setState.withLock(\.handler) } + set { setState.withLock { $0.handler = newValue } } + } + public func set(userId: Int) { + let setHandler = setState.withLock { state in + state.callCount += 1 + return state.handler + } + if let setHandler = setHandler { + setHandler(userId) + } + + } + + private let getUserIDState = MockoloMutex(MockoloHandlerState Int?>()) + public var getUserIDCallCount: Int { + return getUserIDState.withLock(\.callCount) + } + public var getUserIDHandler: (@Sendable () -> Int?)? { + get { getUserIDState.withLock(\.handler) } + set { getUserIDState.withLock { $0.handler = newValue } } + } + public func getUserID() -> Int? { + let getUserIDHandler = getUserIDState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getUserIDHandler = getUserIDHandler { + return getUserIDHandler() + } + return nil + } + + private let publisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var publisherCallCount: Int { + return publisherState.withLock(\.callCount) + } + public var publisherHandler: (@Sendable () throws -> AnyPublisher)? { + get { publisherState.withLock(\.handler) } + set { publisherState.withLock { $0.handler = newValue } } + } + public func publisher() throws -> AnyPublisher { + let publisherHandler = publisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let publisherHandler = publisherHandler { + return try publisherHandler() + } + fatalError("publisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([DownloadDataTask]) -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(tasks: [DownloadDataTask]) { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + addToDownloadQueueHandler(tasks) + } + + } + + private let saveOfflineProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var saveOfflineProgressCallCount: Int { + return saveOfflineProgressState.withLock(\.callCount) + } + public var saveOfflineProgressHandler: (@Sendable (OfflineProgress) async -> ())? { + get { saveOfflineProgressState.withLock(\.handler) } + set { saveOfflineProgressState.withLock { $0.handler = newValue } } + } + public func saveOfflineProgress(progress: OfflineProgress) async { + let saveOfflineProgressHandler = saveOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveOfflineProgressHandler = saveOfflineProgressHandler { + await saveOfflineProgressHandler(progress) + } + + } + + private let loadProgressState = MockoloMutex(MockoloHandlerState OfflineProgress?>()) + public var loadProgressCallCount: Int { + return loadProgressState.withLock(\.callCount) + } + public var loadProgressHandler: (@Sendable (String) async -> OfflineProgress?)? { + get { loadProgressState.withLock(\.handler) } + set { loadProgressState.withLock { $0.handler = newValue } } + } + public func loadProgress(for blockID: String) async -> OfflineProgress? { + let loadProgressHandler = loadProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadProgressHandler = loadProgressHandler { + return await loadProgressHandler(blockID) + } + return nil + } + + private let loadAllOfflineProgressState = MockoloMutex(MockoloHandlerState [OfflineProgress]>()) + public var loadAllOfflineProgressCallCount: Int { + return loadAllOfflineProgressState.withLock(\.callCount) + } + public var loadAllOfflineProgressHandler: (@Sendable () async -> [OfflineProgress])? { + get { loadAllOfflineProgressState.withLock(\.handler) } + set { loadAllOfflineProgressState.withLock { $0.handler = newValue } } + } + public func loadAllOfflineProgress() async -> [OfflineProgress] { + let loadAllOfflineProgressHandler = loadAllOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadAllOfflineProgressHandler = loadAllOfflineProgressHandler { + return await loadAllOfflineProgressHandler() + } + return [OfflineProgress]() + } + + private let deleteProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteProgressCallCount: Int { + return deleteProgressState.withLock(\.callCount) + } + public var deleteProgressHandler: (@Sendable (String) async -> ())? { + get { deleteProgressState.withLock(\.handler) } + set { deleteProgressState.withLock { $0.handler = newValue } } + } + public func deleteProgress(for blockID: String) async { + let deleteProgressHandler = deleteProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteProgressHandler = deleteProgressHandler { + await deleteProgressHandler(blockID) + } + + } + + private let deleteAllProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllProgressCallCount: Int { + return deleteAllProgressState.withLock(\.callCount) + } + public var deleteAllProgressHandler: (@Sendable () async -> ())? { + get { deleteAllProgressState.withLock(\.handler) } + set { deleteAllProgressState.withLock { $0.handler = newValue } } + } + public func deleteAllProgress() async { + let deleteAllProgressHandler = deleteAllProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllProgressHandler = deleteAllProgressHandler { + await deleteAllProgressHandler() + } + + } + + private let addToDownloadQueueBlocksState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueBlocksCallCount: Int { + return addToDownloadQueueBlocksState.withLock(\.callCount) + } + public var addToDownloadQueueBlocksHandler: (@Sendable ([CourseBlock], DownloadQuality) -> ())? { + get { addToDownloadQueueBlocksState.withLock(\.handler) } + set { addToDownloadQueueBlocksState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { + let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksHandler { + addToDownloadQueueBlocksHandler(blocks, downloadQuality) + } + + } + + private let updateTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var updateTaskCallCount: Int { + return updateTaskState.withLock(\.callCount) + } + public var updateTaskHandler: (@Sendable (DownloadDataTask) -> ())? { + get { updateTaskState.withLock(\.handler) } + set { updateTaskState.withLock { $0.handler = newValue } } + } + public func updateTask(task: DownloadDataTask) { + let updateTaskHandler = updateTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateTaskHandler = updateTaskHandler { + updateTaskHandler(task) + } + + } + + private let downloadDataTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadDataTaskCallCount: Int { + return downloadDataTaskState.withLock(\.callCount) + } + public var downloadDataTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadDataTaskState.withLock(\.handler) } + set { downloadDataTaskState.withLock { $0.handler = newValue } } + } + public func downloadDataTask(for blockId: String) async -> DownloadDataTask? { + let downloadDataTaskHandler = downloadDataTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadDataTaskHandler = downloadDataTaskHandler { + return await downloadDataTaskHandler(blockId) + } + return nil + } + + private let getDownloadDataTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksCallCount: Int { + return getDownloadDataTasksState.withLock(\.callCount) + } + public var getDownloadDataTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadDataTasksState.withLock(\.handler) } + set { getDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasks() async -> [DownloadDataTask] { + let getDownloadDataTasksHandler = getDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksHandler = getDownloadDataTasksHandler { + return await getDownloadDataTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadDataTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksForCourseCallCount: Int { + return getDownloadDataTasksForCourseState.withLock(\.callCount) + } + public var getDownloadDataTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadDataTasksForCourseState.withLock(\.handler) } + set { getDownloadDataTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseHandler { + return await getDownloadDataTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let deleteDownloadDataTasksState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteDownloadDataTasksCallCount: Int { + return deleteDownloadDataTasksState.withLock(\.callCount) + } + public var deleteDownloadDataTasksHandler: (@Sendable ([String]) -> ())? { + get { deleteDownloadDataTasksState.withLock(\.handler) } + set { deleteDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func deleteDownloadDataTasks(ids: [String]) { + let deleteDownloadDataTasksHandler = deleteDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteDownloadDataTasksHandler = deleteDownloadDataTasksHandler { + deleteDownloadDataTasksHandler(ids) + } + + } +} + +public final class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseBlocksCallCount: Int { + return getCourseBlocksState.withLock(\.callCount) + } + public var getCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getCourseBlocksState.withLock(\.handler) } + set { getCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseBlocks(courseID: String) async throws -> CourseStructure { + let getCourseBlocksHandler = getCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseBlocksHandler = getCourseBlocksHandler { + return try await getCourseBlocksHandler(courseID) + } + fatalError("getCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getLoadedCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getLoadedCourseBlocksCallCount: Int { + return getLoadedCourseBlocksState.withLock(\.callCount) + } + public var getLoadedCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getLoadedCourseBlocksState.withLock(\.handler) } + set { getLoadedCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure { + let getLoadedCourseBlocksHandler = getLoadedCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseBlocksHandler = getLoadedCourseBlocksHandler { + return try await getLoadedCourseBlocksHandler(courseID) + } + fatalError("getLoadedCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let shiftDueDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var shiftDueDatesCallCount: Int { + return shiftDueDatesState.withLock(\.callCount) + } + public var shiftDueDatesHandler: (@Sendable (String) async throws -> ())? { + get { shiftDueDatesState.withLock(\.handler) } + set { shiftDueDatesState.withLock { $0.handler = newValue } } + } + public func shiftDueDates(courseID: String) async throws { + let shiftDueDatesHandler = shiftDueDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let shiftDueDatesHandler = shiftDueDatesHandler { + try await shiftDueDatesHandler(courseID) + } + + } +} + +public final class DiscussionInteractorProtocolMock: DiscussionInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseDiscussionInfoState = MockoloMutex(MockoloHandlerState DiscussionInfo>()) + public var getCourseDiscussionInfoCallCount: Int { + return getCourseDiscussionInfoState.withLock(\.callCount) + } + public var getCourseDiscussionInfoHandler: (@Sendable (String) async throws -> DiscussionInfo)? { + get { getCourseDiscussionInfoState.withLock(\.handler) } + set { getCourseDiscussionInfoState.withLock { $0.handler = newValue } } + } + public func getCourseDiscussionInfo(courseID: String) async throws -> DiscussionInfo { + let getCourseDiscussionInfoHandler = getCourseDiscussionInfoState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDiscussionInfoHandler = getCourseDiscussionInfoHandler { + return try await getCourseDiscussionInfoHandler(courseID) + } + fatalError("getCourseDiscussionInfoHandler returns can't have a default value thus its handler must be set") + } + + private let getThreadsListState = MockoloMutex(MockoloHandlerState ThreadLists>()) + public var getThreadsListCallCount: Int { + return getThreadsListState.withLock(\.callCount) + } + public var getThreadsListHandler: (@Sendable (String, ThreadType, SortType, ThreadsFilter, Int) async throws -> ThreadLists)? { + get { getThreadsListState.withLock(\.handler) } + set { getThreadsListState.withLock { $0.handler = newValue } } + } + public func getThreadsList(courseID: String, type: ThreadType, sort: SortType, filter: ThreadsFilter, page: Int) async throws -> ThreadLists { + let getThreadsListHandler = getThreadsListState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getThreadsListHandler = getThreadsListHandler { + return try await getThreadsListHandler(courseID, type, sort, filter, page) + } + fatalError("getThreadsListHandler returns can't have a default value thus its handler must be set") + } + + private let getTopicsState = MockoloMutex(MockoloHandlerState Topics>()) + public var getTopicsCallCount: Int { + return getTopicsState.withLock(\.callCount) + } + public var getTopicsHandler: (@Sendable (String) async throws -> Topics)? { + get { getTopicsState.withLock(\.handler) } + set { getTopicsState.withLock { $0.handler = newValue } } + } + public func getTopics(courseID: String) async throws -> Topics { + let getTopicsHandler = getTopicsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getTopicsHandler = getTopicsHandler { + return try await getTopicsHandler(courseID) + } + fatalError("getTopicsHandler returns can't have a default value thus its handler must be set") + } + + private let getTopicState = MockoloMutex(MockoloHandlerState Topics>()) + public var getTopicCallCount: Int { + return getTopicState.withLock(\.callCount) + } + public var getTopicHandler: (@Sendable (String, String) async throws -> Topics)? { + get { getTopicState.withLock(\.handler) } + set { getTopicState.withLock { $0.handler = newValue } } + } + public func getTopic(courseID: String, topicID: String) async throws -> Topics { + let getTopicHandler = getTopicState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getTopicHandler = getTopicHandler { + return try await getTopicHandler(courseID, topicID) + } + fatalError("getTopicHandler returns can't have a default value thus its handler must be set") + } + + private let searchThreadsState = MockoloMutex(MockoloHandlerState ThreadLists>()) + public var searchThreadsCallCount: Int { + return searchThreadsState.withLock(\.callCount) + } + public var searchThreadsHandler: (@Sendable (String, String, Int) async throws -> ThreadLists)? { + get { searchThreadsState.withLock(\.handler) } + set { searchThreadsState.withLock { $0.handler = newValue } } + } + public func searchThreads(courseID: String, searchText: String, pageNumber: Int) async throws -> ThreadLists { + let searchThreadsHandler = searchThreadsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let searchThreadsHandler = searchThreadsHandler { + return try await searchThreadsHandler(courseID, searchText, pageNumber) + } + fatalError("searchThreadsHandler returns can't have a default value thus its handler must be set") + } + + private let getThreadState = MockoloMutex(MockoloHandlerState UserThread>()) + public var getThreadCallCount: Int { + return getThreadState.withLock(\.callCount) + } + public var getThreadHandler: (@Sendable (String) async throws -> UserThread)? { + get { getThreadState.withLock(\.handler) } + set { getThreadState.withLock { $0.handler = newValue } } + } + public func getThread(threadID: String) async throws -> UserThread { + let getThreadHandler = getThreadState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getThreadHandler = getThreadHandler { + return try await getThreadHandler(threadID) + } + fatalError("getThreadHandler returns can't have a default value thus its handler must be set") + } + + private let getDiscussionCommentsState = MockoloMutex(MockoloHandlerState ([UserComment], Pagination)>()) + public var getDiscussionCommentsCallCount: Int { + return getDiscussionCommentsState.withLock(\.callCount) + } + public var getDiscussionCommentsHandler: (@Sendable (String, Int) async throws -> ([UserComment], Pagination))? { + get { getDiscussionCommentsState.withLock(\.handler) } + set { getDiscussionCommentsState.withLock { $0.handler = newValue } } + } + public func getDiscussionComments(threadID: String, page: Int) async throws -> ([UserComment], Pagination) { + let getDiscussionCommentsHandler = getDiscussionCommentsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDiscussionCommentsHandler = getDiscussionCommentsHandler { + return try await getDiscussionCommentsHandler(threadID, page) + } + fatalError("getDiscussionCommentsHandler returns can't have a default value thus its handler must be set") + } + + private let getQuestionCommentsState = MockoloMutex(MockoloHandlerState ([UserComment], Pagination)>()) + public var getQuestionCommentsCallCount: Int { + return getQuestionCommentsState.withLock(\.callCount) + } + public var getQuestionCommentsHandler: (@Sendable (String, Int) async throws -> ([UserComment], Pagination))? { + get { getQuestionCommentsState.withLock(\.handler) } + set { getQuestionCommentsState.withLock { $0.handler = newValue } } + } + public func getQuestionComments(threadID: String, page: Int) async throws -> ([UserComment], Pagination) { + let getQuestionCommentsHandler = getQuestionCommentsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getQuestionCommentsHandler = getQuestionCommentsHandler { + return try await getQuestionCommentsHandler(threadID, page) + } + fatalError("getQuestionCommentsHandler returns can't have a default value thus its handler must be set") + } + + private let getCommentResponsesState = MockoloMutex(MockoloHandlerState ([UserComment], Pagination)>()) + public var getCommentResponsesCallCount: Int { + return getCommentResponsesState.withLock(\.callCount) + } + public var getCommentResponsesHandler: (@Sendable (String, Int) async throws -> ([UserComment], Pagination))? { + get { getCommentResponsesState.withLock(\.handler) } + set { getCommentResponsesState.withLock { $0.handler = newValue } } + } + public func getCommentResponses(commentID: String, page: Int) async throws -> ([UserComment], Pagination) { + let getCommentResponsesHandler = getCommentResponsesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCommentResponsesHandler = getCommentResponsesHandler { + return try await getCommentResponsesHandler(commentID, page) + } + fatalError("getCommentResponsesHandler returns can't have a default value thus its handler must be set") + } + + private let getResponseState = MockoloMutex(MockoloHandlerState UserComment>()) + public var getResponseCallCount: Int { + return getResponseState.withLock(\.callCount) + } + public var getResponseHandler: (@Sendable (String) async throws -> UserComment)? { + get { getResponseState.withLock(\.handler) } + set { getResponseState.withLock { $0.handler = newValue } } + } + public func getResponse(responseID: String) async throws -> UserComment { + let getResponseHandler = getResponseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getResponseHandler = getResponseHandler { + return try await getResponseHandler(responseID) + } + fatalError("getResponseHandler returns can't have a default value thus its handler must be set") + } + + private let addCommentToState = MockoloMutex(MockoloHandlerState Post>()) + public var addCommentToCallCount: Int { + return addCommentToState.withLock(\.callCount) + } + public var addCommentToHandler: (@Sendable (String, String, String?) async throws -> Post)? { + get { addCommentToState.withLock(\.handler) } + set { addCommentToState.withLock { $0.handler = newValue } } + } + public func addCommentTo(threadID: String, rawBody: String, parentID: String?) async throws -> Post { + let addCommentToHandler = addCommentToState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addCommentToHandler = addCommentToHandler { + return try await addCommentToHandler(threadID, rawBody, parentID) + } + fatalError("addCommentToHandler returns can't have a default value thus its handler must be set") + } + + private let voteThreadState = MockoloMutex(MockoloHandlerState ()>()) + public var voteThreadCallCount: Int { + return voteThreadState.withLock(\.callCount) + } + public var voteThreadHandler: (@Sendable (Bool, String) async throws -> ())? { + get { voteThreadState.withLock(\.handler) } + set { voteThreadState.withLock { $0.handler = newValue } } + } + public func voteThread(voted: Bool, threadID: String) async throws { + let voteThreadHandler = voteThreadState.withLock { state in + state.callCount += 1 + return state.handler + } + if let voteThreadHandler = voteThreadHandler { + try await voteThreadHandler(voted, threadID) + } + + } + + private let voteResponseState = MockoloMutex(MockoloHandlerState ()>()) + public var voteResponseCallCount: Int { + return voteResponseState.withLock(\.callCount) + } + public var voteResponseHandler: (@Sendable (Bool, String) async throws -> ())? { + get { voteResponseState.withLock(\.handler) } + set { voteResponseState.withLock { $0.handler = newValue } } + } + public func voteResponse(voted: Bool, responseID: String) async throws { + let voteResponseHandler = voteResponseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let voteResponseHandler = voteResponseHandler { + try await voteResponseHandler(voted, responseID) + } + + } + + private let flagThreadState = MockoloMutex(MockoloHandlerState ()>()) + public var flagThreadCallCount: Int { + return flagThreadState.withLock(\.callCount) + } + public var flagThreadHandler: (@Sendable (Bool, String) async throws -> ())? { + get { flagThreadState.withLock(\.handler) } + set { flagThreadState.withLock { $0.handler = newValue } } + } + public func flagThread(abuseFlagged: Bool, threadID: String) async throws { + let flagThreadHandler = flagThreadState.withLock { state in + state.callCount += 1 + return state.handler + } + if let flagThreadHandler = flagThreadHandler { + try await flagThreadHandler(abuseFlagged, threadID) + } + + } + + private let flagCommentState = MockoloMutex(MockoloHandlerState ()>()) + public var flagCommentCallCount: Int { + return flagCommentState.withLock(\.callCount) + } + public var flagCommentHandler: (@Sendable (Bool, String) async throws -> ())? { + get { flagCommentState.withLock(\.handler) } + set { flagCommentState.withLock { $0.handler = newValue } } + } + public func flagComment(abuseFlagged: Bool, commentID: String) async throws { + let flagCommentHandler = flagCommentState.withLock { state in + state.callCount += 1 + return state.handler + } + if let flagCommentHandler = flagCommentHandler { + try await flagCommentHandler(abuseFlagged, commentID) + } + + } + + private let followThreadState = MockoloMutex(MockoloHandlerState ()>()) + public var followThreadCallCount: Int { + return followThreadState.withLock(\.callCount) + } + public var followThreadHandler: (@Sendable (Bool, String) async throws -> ())? { + get { followThreadState.withLock(\.handler) } + set { followThreadState.withLock { $0.handler = newValue } } + } + public func followThread(following: Bool, threadID: String) async throws { + let followThreadHandler = followThreadState.withLock { state in + state.callCount += 1 + return state.handler + } + if let followThreadHandler = followThreadHandler { + try await followThreadHandler(following, threadID) + } + + } + + private let createNewThreadState = MockoloMutex(MockoloHandlerState ()>()) + public var createNewThreadCallCount: Int { + return createNewThreadState.withLock(\.callCount) + } + public var createNewThreadHandler: (@Sendable (DiscussionNewThread) async throws -> ())? { + get { createNewThreadState.withLock(\.handler) } + set { createNewThreadState.withLock { $0.handler = newValue } } + } + public func createNewThread(newThread: DiscussionNewThread) async throws { + let createNewThreadHandler = createNewThreadState.withLock { state in + state.callCount += 1 + return state.handler + } + if let createNewThreadHandler = createNewThreadHandler { + try await createNewThreadHandler(newThread) + } + + } + + private let readBodyState = MockoloMutex(MockoloHandlerState ()>()) + public var readBodyCallCount: Int { + return readBodyState.withLock(\.callCount) + } + public var readBodyHandler: (@Sendable (String) async throws -> ())? { + get { readBodyState.withLock(\.handler) } + set { readBodyState.withLock { $0.handler = newValue } } + } + public func readBody(threadID: String) async throws { + let readBodyHandler = readBodyState.withLock { state in + state.callCount += 1 + return state.handler + } + if let readBodyHandler = readBodyHandler { + try await readBodyHandler(threadID) + } + + } +} + +public final class DiscussionRouterMock: DiscussionRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let showUserDetailsState = MockoloMutex(MockoloHandlerState ()>()) + public var showUserDetailsCallCount: Int { + return showUserDetailsState.withLock(\.callCount) + } + public var showUserDetailsHandler: (@Sendable (String) -> ())? { + get { showUserDetailsState.withLock(\.handler) } + set { showUserDetailsState.withLock { $0.handler = newValue } } + } + public func showUserDetails(username: String) { + let showUserDetailsHandler = showUserDetailsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showUserDetailsHandler = showUserDetailsHandler { + showUserDetailsHandler(username) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let showThreadsState = MockoloMutex(MockoloHandlerState ()>()) + public var showThreadsCallCount: Int { + return showThreadsState.withLock(\.callCount) + } + public var showThreadsHandler: (@Sendable (String, Topics, String, ThreadType, Bool, Bool) -> ())? { + get { showThreadsState.withLock(\.handler) } + set { showThreadsState.withLock { $0.handler = newValue } } + } + public func showThreads(courseID: String, topics: Topics, title: String, type: ThreadType, isBlackedOut: Bool, animated: Bool) { + let showThreadsHandler = showThreadsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showThreadsHandler = showThreadsHandler { + showThreadsHandler(courseID, topics, title, type, isBlackedOut, animated) + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showThreadState = MockoloMutex(MockoloHandlerState, Bool, Bool) -> ()>()) + public var showThreadCallCount: Int { + return showThreadState.withLock(\.callCount) + } + public var showThreadHandler: (@Sendable (UserThread, CurrentValueSubject, Bool, Bool) -> ())? { + get { showThreadState.withLock(\.handler) } + set { showThreadState.withLock { $0.handler = newValue } } + } + public func showThread(thread: UserThread, postStateSubject: CurrentValueSubject, isBlackedOut: Bool, animated: Bool) { + let showThreadHandler = showThreadState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showThreadHandler = showThreadHandler { + showThreadHandler(thread, postStateSubject, isBlackedOut, animated) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showDiscussionsSearchState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscussionsSearchCallCount: Int { + return showDiscussionsSearchState.withLock(\.callCount) + } + public var showDiscussionsSearchHandler: (@Sendable (String, Bool) -> ())? { + get { showDiscussionsSearchState.withLock(\.handler) } + set { showDiscussionsSearchState.withLock { $0.handler = newValue } } + } + public func showDiscussionsSearch(courseID: String, isBlackedOut: Bool) { + let showDiscussionsSearchHandler = showDiscussionsSearchState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscussionsSearchHandler = showDiscussionsSearchHandler { + showDiscussionsSearchHandler(courseID, isBlackedOut) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showCommentsState = MockoloMutex(MockoloHandlerState, Bool, Bool) -> ()>()) + public var showCommentsCallCount: Int { + return showCommentsState.withLock(\.callCount) + } + public var showCommentsHandler: (@Sendable (String, String, Post, CurrentValueSubject, Bool, Bool) -> ())? { + get { showCommentsState.withLock(\.handler) } + set { showCommentsState.withLock { $0.handler = newValue } } + } + public func showComments(courseID: String, commentID: String, parentComment: Post, threadStateSubject: CurrentValueSubject, isBlackedOut: Bool, animated: Bool) { + let showCommentsHandler = showCommentsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showCommentsHandler = showCommentsHandler { + showCommentsHandler(courseID, commentID, parentComment, threadStateSubject, isBlackedOut, animated) + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let createNewThreadState = MockoloMutex(MockoloHandlerState Void) -> ()>()) + public var createNewThreadCallCount: Int { + return createNewThreadState.withLock(\.callCount) + } + public var createNewThreadHandler: (@Sendable (String, String, @escaping () -> Void) -> ())? { + get { createNewThreadState.withLock(\.handler) } + set { createNewThreadState.withLock { $0.handler = newValue } } + } + public func createNewThread(courseID: String, selectedTopic: String, onPostCreated: @escaping () -> Void) { + let createNewThreadHandler = createNewThreadState.withLock { state in + state.callCount += 1 + return state.handler + } + if let createNewThreadHandler = createNewThreadHandler { + createNewThreadHandler(courseID, selectedTopic, onPostCreated) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class ConnectivityProtocolMock: ConnectivityProtocol, @unchecked Sendable { + public init() { } + public init(isInternetAvaliable: Bool = false, isMobileData: Bool = false) { + self.isInternetAvaliable = isInternetAvaliable + self.isMobileData = isMobileData + } + + + + public var isInternetAvaliable: Bool = false + + + public var isMobileData: Bool = false + + + private var _internetReachableSubject: CurrentValueSubject! + public var internetReachableSubject: CurrentValueSubject { + get { return _internetReachableSubject } + set { _internetReachableSubject = newValue } + } +} + +public final class DownloadManagerProtocolMock: DownloadManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCurrentDownloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var getCurrentDownloadTaskCallCount: Int { + return getCurrentDownloadTaskState.withLock(\.callCount) + } + public var getCurrentDownloadTaskHandler: (@Sendable () async -> DownloadDataTask?)? { + get { getCurrentDownloadTaskState.withLock(\.handler) } + set { getCurrentDownloadTaskState.withLock { $0.handler = newValue } } + } + public func getCurrentDownloadTask() async -> DownloadDataTask? { + let getCurrentDownloadTaskHandler = getCurrentDownloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCurrentDownloadTaskHandler = getCurrentDownloadTaskHandler { + return await getCurrentDownloadTaskHandler() + } + return nil + } + + private let eventPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var eventPublisherCallCount: Int { + return eventPublisherState.withLock(\.callCount) + } + public var eventPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { eventPublisherState.withLock(\.handler) } + set { eventPublisherState.withLock { $0.handler = newValue } } + } + public func eventPublisher() -> AnyPublisher { + let eventPublisherHandler = eventPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let eventPublisherHandler = eventPublisherHandler { + return eventPublisherHandler() + } + fatalError("eventPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([CourseBlock]) async throws -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock]) async throws { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + try await addToDownloadQueueHandler(blocks) + } + + } + + private let getDownloadTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksCallCount: Int { + return getDownloadTasksState.withLock(\.callCount) + } + public var getDownloadTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadTasksState.withLock(\.handler) } + set { getDownloadTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadTasks() async -> [DownloadDataTask] { + let getDownloadTasksHandler = getDownloadTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksHandler = getDownloadTasksHandler { + return await getDownloadTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksForCourseCallCount: Int { + return getDownloadTasksForCourseState.withLock(\.callCount) + } + public var getDownloadTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadTasksForCourseState.withLock(\.handler) } + set { getDownloadTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadTasksForCourseHandler = getDownloadTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksForCourseHandler = getDownloadTasksForCourseHandler { + return await getDownloadTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let cancelDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCallCount: Int { + return cancelDownloadingState.withLock(\.callCount) + } + public var cancelDownloadingHandler: (@Sendable (String, [CourseBlock]) async throws -> ())? { + get { cancelDownloadingState.withLock(\.handler) } + set { cancelDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String, blocks: [CourseBlock]) async throws { + let cancelDownloadingHandler = cancelDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingHandler = cancelDownloadingHandler { + try await cancelDownloadingHandler(courseId, blocks) + } + + } + + private let cancelDownloadingTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingTaskCallCount: Int { + return cancelDownloadingTaskState.withLock(\.callCount) + } + public var cancelDownloadingTaskHandler: (@Sendable (DownloadDataTask) async throws -> ())? { + get { cancelDownloadingTaskState.withLock(\.handler) } + set { cancelDownloadingTaskState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(task: DownloadDataTask) async throws { + let cancelDownloadingTaskHandler = cancelDownloadingTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingTaskHandler = cancelDownloadingTaskHandler { + try await cancelDownloadingTaskHandler(task) + } + + } + + private let cancelDownloadingCourseIdState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCourseIdCallCount: Int { + return cancelDownloadingCourseIdState.withLock(\.callCount) + } + public var cancelDownloadingCourseIdHandler: (@Sendable (String) async throws -> ())? { + get { cancelDownloadingCourseIdState.withLock(\.handler) } + set { cancelDownloadingCourseIdState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String) async throws { + let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdHandler { + try await cancelDownloadingCourseIdHandler(courseId) + } + + } + + private let cancelAllDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelAllDownloadingCallCount: Int { + return cancelAllDownloadingState.withLock(\.callCount) + } + public var cancelAllDownloadingHandler: (@Sendable () async throws -> ())? { + get { cancelAllDownloadingState.withLock(\.handler) } + set { cancelAllDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelAllDownloading() async throws { + let cancelAllDownloadingHandler = cancelAllDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelAllDownloadingHandler = cancelAllDownloadingHandler { + try await cancelAllDownloadingHandler() + } + + } + + private let deleteAllState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllCallCount: Int { + return deleteAllState.withLock(\.callCount) + } + public var deleteAllHandler: (@Sendable () async -> ())? { + get { deleteAllState.withLock(\.handler) } + set { deleteAllState.withLock { $0.handler = newValue } } + } + public func deleteAll() async { + let deleteAllHandler = deleteAllState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllHandler = deleteAllHandler { + await deleteAllHandler() + } + + } + + private let fileUrlState = MockoloMutex(MockoloHandlerState URL?>()) + public var fileUrlCallCount: Int { + return fileUrlState.withLock(\.callCount) + } + public var fileUrlHandler: (@Sendable (String) async -> URL?)? { + get { fileUrlState.withLock(\.handler) } + set { fileUrlState.withLock { $0.handler = newValue } } + } + public func fileUrl(for blockId: String) async -> URL? { + let fileUrlHandler = fileUrlState.withLock { state in + state.callCount += 1 + return state.handler + } + if let fileUrlHandler = fileUrlHandler { + return await fileUrlHandler(blockId) + } + return nil + } + + private let resumeDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var resumeDownloadingCallCount: Int { + return resumeDownloadingState.withLock(\.callCount) + } + public var resumeDownloadingHandler: (@Sendable () async throws -> ())? { + get { resumeDownloadingState.withLock(\.handler) } + set { resumeDownloadingState.withLock { $0.handler = newValue } } + } + public func resumeDownloading() async throws { + let resumeDownloadingHandler = resumeDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resumeDownloadingHandler = resumeDownloadingHandler { + try await resumeDownloadingHandler() + } + + } + + private let isLargeVideosSizeState = MockoloMutex(MockoloHandlerState Bool>()) + public var isLargeVideosSizeCallCount: Int { + return isLargeVideosSizeState.withLock(\.callCount) + } + public var isLargeVideosSizeHandler: (@Sendable ([CourseBlock]) async -> Bool)? { + get { isLargeVideosSizeState.withLock(\.handler) } + set { isLargeVideosSizeState.withLock { $0.handler = newValue } } + } + public func isLargeVideosSize(blocks: [CourseBlock]) async -> Bool { + let isLargeVideosSizeHandler = isLargeVideosSizeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isLargeVideosSizeHandler = isLargeVideosSizeHandler { + return await isLargeVideosSizeHandler(blocks) + } + return false + } + + private let removeAppSupportDirectoryUnusedContentState = MockoloMutex(MockoloHandlerState ()>()) + public var removeAppSupportDirectoryUnusedContentCallCount: Int { + return removeAppSupportDirectoryUnusedContentState.withLock(\.callCount) + } + public var removeAppSupportDirectoryUnusedContentHandler: (@Sendable () -> ())? { + get { removeAppSupportDirectoryUnusedContentState.withLock(\.handler) } + set { removeAppSupportDirectoryUnusedContentState.withLock { $0.handler = newValue } } + } + public func removeAppSupportDirectoryUnusedContent() { + let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentHandler { + removeAppSupportDirectoryUnusedContentHandler() + } + + } + + private let deleteState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteCallCount: Int { + return deleteState.withLock(\.callCount) + } + public var deleteHandler: (@Sendable ([CourseBlock], String) async -> ())? { + get { deleteState.withLock(\.handler) } + set { deleteState.withLock { $0.handler = newValue } } + } + public func delete(blocks: [CourseBlock], courseId: String) async { + let deleteHandler = deleteState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteHandler = deleteHandler { + await deleteHandler(blocks, courseId) + } + + } + + private let downloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadTaskCallCount: Int { + return downloadTaskState.withLock(\.callCount) + } + public var downloadTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadTaskState.withLock(\.handler) } + set { downloadTaskState.withLock { $0.handler = newValue } } + } + public func downloadTask(for blockId: String) async -> DownloadDataTask? { + let downloadTaskHandler = downloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadTaskHandler = downloadTaskHandler { + return await downloadTaskHandler(blockId) + } + return nil + } + + private let getFreeDiskSpaceState = MockoloMutex(MockoloHandlerState Int?>()) + public var getFreeDiskSpaceCallCount: Int { + return getFreeDiskSpaceState.withLock(\.callCount) + } + public var getFreeDiskSpaceHandler: (@Sendable () -> Int?)? { + get { getFreeDiskSpaceState.withLock(\.handler) } + set { getFreeDiskSpaceState.withLock { $0.handler = newValue } } + } + public func getFreeDiskSpace() -> Int? { + let getFreeDiskSpaceHandler = getFreeDiskSpaceState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getFreeDiskSpaceHandler = getFreeDiskSpaceHandler { + return getFreeDiskSpaceHandler() + } + return nil + } +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { + print("At \(function), the captured arguments are not Sendable, it is not concurrency-safe.") +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { +} + +/// Will be replaced to `Synchronization.Mutex` in future. +fileprivate final class MockoloMutex: @unchecked Sendable { + private let lock = NSLock() + private var value: Value + init(_ initialValue: Value) { + self.value = initialValue + } +#if compiler(>=6.0) + borrowing func withLock(_ body: (inout sending Value) throws(E) -> Result) throws(E) -> sending Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#else + func withLock(_ body: (inout Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#endif +} + +fileprivate struct MockoloUnsafeTransfer: @unchecked Sendable { + var value: Value + init(_ value: Value) { + self.value = value + } +} + +fileprivate struct MockoloHandlerState { + var argValues: [MockoloUnsafeTransfer] = [] + var handler: Handler? = nil + var callCount: Int = 0 +} + diff --git a/Discussion/DiscussionTests/Presentation/Comment/Base/BaseResponsesViewModelTests.swift b/Discussion/DiscussionTests/Presentation/Comment/Base/BaseResponsesViewModelTests.swift index 88aa56ca4..8b2aaff31 100644 --- a/Discussion/DiscussionTests/Presentation/Comment/Base/BaseResponsesViewModelTests.swift +++ b/Discussion/DiscussionTests/Presentation/Comment/Base/BaseResponsesViewModelTests.swift @@ -2,10 +2,9 @@ // BaseResponsesViewModelTests.swift // DiscussionTests // -// Created by  Stepanok Ivan on 31.01.2023. +// Created by Stepanok Ivan on 31.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Discussion @@ -14,7 +13,7 @@ import SwiftUI @MainActor final class BaseResponsesViewModelTests: XCTestCase { - + let post = Post(authorName: "1", authorAvatar: "1", postDate: Date(), @@ -50,18 +49,18 @@ final class BaseResponsesViewModelTests: XCTestCase { parentID: nil, abuseFlagged: false, closed: false) - + var interactor: DiscussionInteractorProtocolMock! var router: DiscussionRouterMock! - var config: ConfigMock! + var config: ConfigProtocolMock! var viewModel: BaseResponsesViewModel! - + override func setUp() async throws { try await super.setUp() - + interactor = DiscussionInteractorProtocolMock() router = DiscussionRouterMock() - config = ConfigMock() + config = ConfigProtocolMock() viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -70,11 +69,11 @@ final class BaseResponsesViewModelTests: XCTestCase { analytics: DiscussionAnalyticsMock() ) } - + func testVoteThreadSuccess() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -85,24 +84,24 @@ final class BaseResponsesViewModelTests: XCTestCase { var result = false viewModel.postComments = post - - Given(interactor, .voteThread(voted: .any, threadID: .any, willProduce: {_ in})) - + + interactor.voteThreadHandler = { _, _ in } + result = await viewModel.vote(id: "1", isThread: true, voted: true, index: 0, courseID: "courseID") - Verify(interactor, .voteThread(voted: .value(true), threadID: .value("1"))) - + XCTAssertEqual(interactor.voteThreadCallCount, 1) + XCTAssertTrue(result) XCTAssertFalse(viewModel.postComments!.comments[0].voted) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.isShowProgress) } - + func testVoteResponseSuccess() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -115,12 +114,12 @@ final class BaseResponsesViewModelTests: XCTestCase { viewModel.postComments = post viewModel.postComments?.comments[0].voted = false - - Given(interactor, .voteResponse(voted: .any, responseID: .any, willProduce: {_ in})) + + interactor.voteResponseHandler = { _, _ in } result = await viewModel.vote(id: "1", isThread: false, voted: true, index: 0, courseID: "courseID") - Verify(interactor, .voteResponse(voted: .value(true), responseID: .value("1"))) + XCTAssertEqual(interactor.voteResponseCallCount, 1) XCTAssertTrue(result) XCTAssertTrue(viewModel.postComments!.comments[0].voted) @@ -128,11 +127,11 @@ final class BaseResponsesViewModelTests: XCTestCase { XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.isShowProgress) } - + func testVoteParentThreadSuccess() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -144,24 +143,24 @@ final class BaseResponsesViewModelTests: XCTestCase { var result = false viewModel.postComments = post - - Given(interactor, .voteThread(voted: .any, threadID: .any, willProduce: {_ in})) - + + interactor.voteThreadHandler = { _, _ in } + result = await viewModel.vote(id: "1", isThread: true, voted: true, index: nil, courseID: "courseID") - Verify(interactor, .voteThread(voted: .value(true), threadID: .value("1"))) - + XCTAssertEqual(interactor.voteThreadCallCount, 1) + XCTAssertTrue(result) XCTAssertTrue(viewModel.postComments!.voted) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.isShowProgress) } - + func testVoteParentResponseSuccess() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -171,16 +170,16 @@ final class BaseResponsesViewModelTests: XCTestCase { ) var result = false - + viewModel.postComments = post - Given(interactor, .voteResponse(voted: .any, responseID: .any, willProduce: {_ in})) + interactor.voteResponseHandler = { _, _ in } viewModel.postComments?.voted = true result = await viewModel.vote(id: "2", isThread: false, voted: false, index: nil, courseID: "courseID") - - Verify(interactor, .voteResponse(voted: .value(false), responseID: .value("2"))) + + XCTAssertEqual(interactor.voteResponseCallCount, 1) XCTAssertTrue(result) XCTAssertFalse(viewModel.postComments!.voted) @@ -188,11 +187,11 @@ final class BaseResponsesViewModelTests: XCTestCase { XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.isShowProgress) } - + func testVoteNoInternetError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -204,23 +203,23 @@ final class BaseResponsesViewModelTests: XCTestCase { var result = false let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .voteThread(voted: .any, threadID: .any, willThrow: noInternetError)) - + + interactor.voteThreadHandler = { _, _ in throw noInternetError } + result = await viewModel.vote(id: "1", isThread: true, voted: true, index: 1, courseID: "courseID") - - Verify(interactor, .voteThread(voted: .value(true), threadID: .value("1"))) - + + XCTAssertEqual(interactor.voteThreadCallCount, 1) + XCTAssertFalse(result) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertFalse(viewModel.isShowProgress) } - + func testVoteUnknownError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -230,23 +229,23 @@ final class BaseResponsesViewModelTests: XCTestCase { ) var result = false - - Given(interactor, .voteThread(voted: .any, threadID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + + interactor.voteThreadHandler = { _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + result = await viewModel.vote(id: "1", isThread: true, voted: true, index: nil, courseID: "courseID") - - Verify(interactor, .voteThread(voted: .value(true), threadID: .value("1"))) - + + XCTAssertEqual(interactor.voteThreadCallCount, 1) + XCTAssertFalse(result) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertFalse(viewModel.isShowProgress) } - + func testFlagThreadSuccess() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -256,26 +255,26 @@ final class BaseResponsesViewModelTests: XCTestCase { ) var result = false - + viewModel.postComments = post - - Given(interactor, .flagThread(abuseFlagged: .any, threadID: .any, willProduce: {_ in})) - + + interactor.flagThreadHandler = { _, _ in } + result = await viewModel.flag(id: "1", isThread: true, abuseFlagged: true, index: nil, courseID: "courseID") - - Verify(interactor, .flagThread(abuseFlagged: .value(true), threadID: .value("1"))) - + + XCTAssertEqual(interactor.flagThreadCallCount, 1) + XCTAssertTrue(result) XCTAssertTrue(viewModel.postComments!.abuseFlagged) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.isShowProgress) } - + func testFlagCommentSuccess() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -285,26 +284,26 @@ final class BaseResponsesViewModelTests: XCTestCase { ) var result = false - + viewModel.postComments = post - - Given(interactor, .flagComment(abuseFlagged: .any, commentID: .any, willProduce: {_ in})) - + + interactor.flagCommentHandler = { _, _ in } + result = await viewModel.flag(id: "1", isThread: false, abuseFlagged: true, index: 0, courseID: "courseID") - - Verify(interactor, .flagComment(abuseFlagged: .value(true), commentID: .value("1"))) - + + XCTAssertEqual(interactor.flagCommentCallCount, 1) + XCTAssertTrue(result) XCTAssertTrue(viewModel.postComments!.comments[0].abuseFlagged) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.isShowProgress) } - + func testFlagNoInternetError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -316,23 +315,23 @@ final class BaseResponsesViewModelTests: XCTestCase { var result = false let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .flagThread(abuseFlagged: .any, threadID: .any, willThrow: noInternetError)) - + + interactor.flagThreadHandler = { _, _ in throw noInternetError } + result = await viewModel.flag(id: "1", isThread: true, abuseFlagged: true, index: 1, courseID: "courseID") - - Verify(interactor, .flagThread(abuseFlagged: .value(true), threadID: .value("1"))) + + XCTAssertEqual(interactor.flagThreadCallCount, 1) XCTAssertFalse(result) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertFalse(viewModel.isShowProgress) } - + func testFlagUnknownError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -343,22 +342,22 @@ final class BaseResponsesViewModelTests: XCTestCase { var result = false - Given(interactor, .flagThread(abuseFlagged: .any, threadID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + interactor.flagThreadHandler = { _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + result = await viewModel.flag(id: "1", isThread: true, abuseFlagged: true, index: nil, courseID: "courseID") - - Verify(interactor, .flagThread(abuseFlagged: .value(true), threadID: .value("1"))) + + XCTAssertEqual(interactor.flagThreadCallCount, 1) XCTAssertFalse(result) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertFalse(viewModel.isShowProgress) } - + func testFollowThreadSuccess() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -368,26 +367,26 @@ final class BaseResponsesViewModelTests: XCTestCase { ) var result = false - + viewModel.postComments = post - Given(interactor, .followThread(following: .any, threadID: .any, willProduce: {_ in})) - + interactor.followThreadHandler = { _, _ in } + result = await viewModel.followThread(following: true, threadID: "1") - - Verify(interactor, .followThread(following: .value(true), threadID: .value("1"))) - + + XCTAssertEqual(interactor.followThreadCallCount, 1) + XCTAssertTrue(result) XCTAssertTrue(viewModel.postComments!.followed) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.isShowProgress) } - + func testFollowThreadNoInternetError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -399,23 +398,23 @@ final class BaseResponsesViewModelTests: XCTestCase { var result = false let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .followThread(following: .any, threadID: .any, willThrow: noInternetError)) - + + interactor.followThreadHandler = { _, _ in throw noInternetError } + result = await viewModel.followThread(following: true, threadID: "1") - Verify(interactor, .followThread(following: .value(true), threadID: .value("1"))) + XCTAssertEqual(interactor.followThreadCallCount, 1) XCTAssertFalse(result) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertFalse(viewModel.isShowProgress) } - + func testFollowThreadUnknownError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -426,22 +425,22 @@ final class BaseResponsesViewModelTests: XCTestCase { var result = false - Given(interactor, .followThread(following: .any, threadID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + interactor.followThreadHandler = { _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + result = await viewModel.followThread(following: true, threadID: "1") - Verify(interactor, .followThread(following: .value(true), threadID: .value("1"))) + XCTAssertEqual(interactor.followThreadCallCount, 1) XCTAssertFalse(result) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertFalse(viewModel.isShowProgress) } - + func testAddNewPost() { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() let viewModel = BaseResponsesViewModel( interactor: interactor, router: router, @@ -449,9 +448,9 @@ final class BaseResponsesViewModelTests: XCTestCase { storage: CoreStorageMock(), analytics: DiscussionAnalyticsMock() ) - + viewModel.postComments = post - + let newPost = Post(authorName: "new", authorAvatar: "new", postDate: Date(), @@ -469,10 +468,10 @@ final class BaseResponsesViewModelTests: XCTestCase { parentID: nil, abuseFlagged: false, closed: false) - + viewModel.addNewPost(newPost) - + XCTAssertTrue(viewModel.postComments!.comments.last!.authorName == "new") } - + } diff --git a/Discussion/DiscussionTests/Presentation/Comment/ThreadViewModelTests.swift b/Discussion/DiscussionTests/Presentation/Comment/ThreadViewModelTests.swift index edbf48414..3700b158a 100644 --- a/Discussion/DiscussionTests/Presentation/Comment/ThreadViewModelTests.swift +++ b/Discussion/DiscussionTests/Presentation/Comment/ThreadViewModelTests.swift @@ -2,10 +2,9 @@ // ThreadViewModelTests.swift // DiscussionTests // -// Created by  Stepanok Ivan on 30.01.2023. +// Created by Stepanok Ivan on 30.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Discussion @@ -14,7 +13,7 @@ import SwiftUI @MainActor final class ThreadViewModelTests: XCTestCase { - + let userComments = [ UserComment(authorName: "1", authorAvatar: "1", @@ -62,7 +61,7 @@ final class ThreadViewModelTests: XCTestCase { parentID: nil, abuseFlagged: false) ] - + let threads = ThreadLists(threads: [ UserThread(id: "1", author: "1", @@ -149,7 +148,7 @@ final class ThreadViewModelTests: XCTestCase { hasEndorsed: true, numPages: 2), ]) - + let postComments = Post(authorName: "1", authorAvatar: "1", postDate: Date(), @@ -207,140 +206,129 @@ final class ThreadViewModelTests: XCTestCase { func testGetQuestionPostsSuccess() async { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() var result = false + interactor.readBodyHandler = { _ in } + interactor.getQuestionCommentsHandler = { _, _ in + (self.userComments, Pagination(next: "", previous: "", count: 1, numPages: 1)) + } + let viewModel = ThreadViewModel(interactor: interactor, router: router, config: config, storage: CoreStorageMock(), postStateSubject: .init(.readed(id: "1")), analytics: DiscussionAnalyticsMock()) - - Given(interactor, .readBody(threadID: .any, willProduce: {_ in})) - Given(interactor, .getQuestionComments(threadID: .any, page: .any, - willReturn: (userComments, Pagination(next: "", - previous: "", - count: 1, - numPages: 1)))) - + result = await viewModel.getThreadData(thread: threads.threads[0], page: 1) - - Verify(interactor, .readBody(threadID: .value(threads.threads[0].id))) - Verify(interactor, .getQuestionComments(threadID: .value(threads.threads[0].id), page: .value(1))) - + + XCTAssertEqual(interactor.readBodyCallCount, 1) + XCTAssertEqual(interactor.getQuestionCommentsCallCount, 1) + XCTAssertTrue(result) XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) } - + func testGetDiscussionPostsSuccess() async { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() var result = false + interactor.readBodyHandler = { _ in } + interactor.getDiscussionCommentsHandler = { _, _ in + (self.userComments, Pagination(next: "", previous: "", count: 1, numPages: 1)) + } + let viewModel = ThreadViewModel(interactor: interactor, router: router, config: config, storage: CoreStorageMock(), postStateSubject: .init(.readed(id: "1")), analytics: DiscussionAnalyticsMock()) - - Given(interactor, .readBody(threadID: .any, willProduce: {_ in})) - Given(interactor, .getDiscussionComments(threadID: .any, page: .any, - willReturn: (userComments, Pagination(next: "", - previous: "", - count: 1, - numPages: 1)))) - + result = await viewModel.getThreadData(thread: threads.threads[1], page: 1) - - Verify(interactor, .readBody(threadID: .value(threads.threads[1].id))) - Verify(interactor, .getDiscussionComments(threadID: .value(threads.threads[1].id), page: .value(1))) - + + XCTAssertEqual(interactor.readBodyCallCount, 1) + XCTAssertEqual(interactor.getDiscussionCommentsCallCount, 1) + XCTAssertTrue(result) XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) } - + func testGetPostsNoInternetError() async { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() var result = false + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) + + interactor.readBodyHandler = { _ in throw noInternetError } + interactor.getQuestionCommentsHandler = { _, _ in throw noInternetError } + let viewModel = ThreadViewModel(interactor: interactor, router: router, config: config, storage: CoreStorageMock(), postStateSubject: .init(.readed(id: "1")), analytics: DiscussionAnalyticsMock()) - - let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .readBody(threadID: .any, willThrow: noInternetError)) - Given(interactor, .getQuestionComments(threadID: .any, page: .any, willThrow: noInternetError)) - + result = await viewModel.getThreadData(thread: threads.threads[0], page: 1) - + viewModel.postComments = postComments - - Verify(interactor, .readBody(threadID: .any)) - Verify(interactor, 0, .getQuestionComments(threadID: .any, page: .any)) - + + XCTAssertEqual(interactor.readBodyCallCount, 1) + XCTAssertEqual(interactor.getQuestionCommentsCallCount, 0) + XCTAssertFalse(result) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) XCTAssertNotNil(viewModel.errorMessage) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) } - - + + func testGetPostsUnknownError() async { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() var result = false + interactor.readBodyHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + interactor.getQuestionCommentsHandler = { _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + let viewModel = ThreadViewModel(interactor: interactor, router: router, config: config, storage: CoreStorageMock(), postStateSubject: .init(.readed(id: "1")), analytics: DiscussionAnalyticsMock()) - - Given(interactor, .readBody(threadID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - Given(interactor, .getQuestionComments(threadID: .any, page: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + result = await viewModel.getThreadData(thread: threads.threads[0], page: 1) - + viewModel.postComments = postComments - - Verify(interactor, .readBody(threadID: .value(threads.threads[0].id))) - Verify(interactor, 0, .getQuestionComments(threadID: .value(threads.threads[0].id), page: .value(1))) - + + XCTAssertEqual(interactor.readBodyCallCount, 1) + XCTAssertEqual(interactor.getQuestionCommentsCallCount, 0) + XCTAssertFalse(result) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) XCTAssertNotNil(viewModel.errorMessage) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) } - + func testPostCommentSuccess() async { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() - let viewModel = ThreadViewModel(interactor: interactor, - router: router, - config: config, - storage: CoreStorageMock(), - postStateSubject: .init(.readed(id: "1")), - analytics: DiscussionAnalyticsMock()) - let post = Post(authorName: "", authorAvatar: "", postDate: Date(), @@ -358,23 +346,34 @@ final class ThreadViewModelTests: XCTestCase { parentID: nil, abuseFlagged: true, closed: false) - - Given(interactor, .addCommentTo(threadID: .any, rawBody: .any, parentID: .any, willReturn: post) ) - + + interactor.addCommentToHandler = { _, _, _ in post } + + let viewModel = ThreadViewModel(interactor: interactor, + router: router, + config: config, + storage: CoreStorageMock(), + postStateSubject: .init(.readed(id: "1")), + analytics: DiscussionAnalyticsMock()) + await viewModel.postComment(courseID: "CourseID", threadID: "1", rawBody: "1", parentID: nil) - - Verify(interactor, .addCommentTo(threadID: .value("1"), rawBody: .value("1"), parentID: .value(nil))) - + + XCTAssertEqual(interactor.addCommentToCallCount, 1) + XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) } - + func testPostCommentNoInternetError() async { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() + + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) + + interactor.addCommentToHandler = { _, _, _ in throw noInternetError } let viewModel = ThreadViewModel(interactor: interactor, router: router, @@ -382,25 +381,23 @@ final class ThreadViewModelTests: XCTestCase { storage: CoreStorageMock(), postStateSubject: .init(.readed(id: "1")), analytics: DiscussionAnalyticsMock()) - - let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .addCommentTo(threadID: .any, rawBody: .any, parentID: .any, willThrow: noInternetError) ) - + await viewModel.postComment(courseID: "CourseID", threadID: "1", rawBody: "1", parentID: nil) - - Verify(interactor, .addCommentTo(threadID: .value("1"), rawBody: .value("1"), parentID: .value(nil))) + + XCTAssertEqual(interactor.addCommentToCallCount, 1) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) XCTAssertNotNil(viewModel.errorMessage) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) } - + func testPostCommentUnknownError() async { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() + + interactor.addCommentToHandler = { _, _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } let viewModel = ThreadViewModel(interactor: interactor, router: router, @@ -408,43 +405,39 @@ final class ThreadViewModelTests: XCTestCase { storage: CoreStorageMock(), postStateSubject: .init(.readed(id: "1")), analytics: DiscussionAnalyticsMock()) - - Given(interactor, .addCommentTo(threadID: .any, rawBody: .any, parentID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil)) ) - + await viewModel.postComment(courseID: "CourseID", threadID: "1", rawBody: "1", parentID: nil) - - Verify(interactor, .addCommentTo(threadID: .value("1"), rawBody: .value("1"), parentID: .value(nil))) + + XCTAssertEqual(interactor.addCommentToCallCount, 1) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) XCTAssertNotNil(viewModel.errorMessage) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) } - + func testFetchMorePosts() async { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() var result = false - + + interactor.getQuestionCommentsHandler = { _, _ in + (self.userComments, Pagination(next: "", previous: "", count: 1, numPages: 1)) + } + let viewModel = ThreadViewModel(interactor: interactor, router: router, config: config, storage: CoreStorageMock(), postStateSubject: .init(.readed(id: "1")), analytics: DiscussionAnalyticsMock()) - + viewModel.totalPages = 2 viewModel.comments = userComments + userComments - - Given(interactor, .getQuestionComments(threadID: .any, page: .any, - willReturn: (userComments, Pagination(next: "", - previous: "", - count: 1, - numPages: 1)))) - + result = await viewModel.fetchMorePosts(thread: threads.threads[0], index: 3) - + XCTAssertTrue(result) } } diff --git a/Discussion/DiscussionTests/Presentation/CreateNewThread/CreateNewThreadViewModelTests.swift b/Discussion/DiscussionTests/Presentation/CreateNewThread/CreateNewThreadViewModelTests.swift index 6512efbcb..8b8dfa19b 100644 --- a/Discussion/DiscussionTests/Presentation/CreateNewThread/CreateNewThreadViewModelTests.swift +++ b/Discussion/DiscussionTests/Presentation/CreateNewThread/CreateNewThreadViewModelTests.swift @@ -2,10 +2,9 @@ // CreateNewThreadViewModelTests.swift // DiscussionTests // -// Created by  Stepanok Ivan on 31.01.2023. +// Created by Stepanok Ivan on 31.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Discussion @@ -14,7 +13,7 @@ import SwiftUI @MainActor final class CreateNewThreadViewModelTests: XCTestCase { - + let newThread = DiscussionNewThread( courseID: "1", topicID: "1", @@ -23,13 +22,15 @@ final class CreateNewThreadViewModelTests: XCTestCase { rawBody: "1", followPost: false ) - + func testCreateNewThreadSuccess() async { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() var result = false - + + interactor.createNewThreadHandler = { _ in } + let viewModel = CreateNewThreadViewModel( interactor: interactor, router: router, @@ -37,26 +38,28 @@ final class CreateNewThreadViewModelTests: XCTestCase { analytics: DiscussionAnalyticsMock(), storage: CoreStorageMock() ) - - Given(interactor, .createNewThread(newThread: .any, willProduce: {_ in})) - + result = await viewModel.createNewThread(newThread: newThread) - - Verify(interactor, .createNewThread(newThread: .any)) - Verify(router, .back(animated: .value(true))) - + + XCTAssertEqual(interactor.createNewThreadCallCount, 1) + XCTAssertEqual(router.backCallCount, 1) + XCTAssertTrue(result) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.isShowProgress) } - + func testCreateNewThreadNoInternetError() async { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() var result = false - + + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) + + interactor.createNewThreadHandler = { _ in throw noInternetError } + let viewModel = CreateNewThreadViewModel( interactor: interactor, router: router, @@ -64,28 +67,26 @@ final class CreateNewThreadViewModelTests: XCTestCase { analytics: DiscussionAnalyticsMock(), storage: CoreStorageMock() ) - - let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .createNewThread(newThread: .any, willThrow: noInternetError)) - + result = await viewModel.createNewThread(newThread: newThread) - - Verify(interactor, .createNewThread(newThread: .any)) - Verify(router, 0, .back(animated: .value(true))) - + + XCTAssertEqual(interactor.createNewThreadCallCount, 1) + XCTAssertEqual(router.backCallCount, 0) + XCTAssertFalse(result) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertFalse(viewModel.isShowProgress) } - + func testCreateNewThreadUnknownError() async { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() var result = false - + + interactor.createNewThreadHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + let viewModel = CreateNewThreadViewModel( interactor: interactor, router: router, @@ -93,14 +94,12 @@ final class CreateNewThreadViewModelTests: XCTestCase { analytics: DiscussionAnalyticsMock(), storage: CoreStorageMock() ) - - Given(interactor, .createNewThread(newThread: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + result = await viewModel.createNewThread(newThread: newThread) - - Verify(interactor, .createNewThread(newThread: .any)) - Verify(router, 0, .back(animated: .value(true))) - + + XCTAssertEqual(interactor.createNewThreadCallCount, 1) + XCTAssertEqual(router.backCallCount, 0) + XCTAssertFalse(result) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) diff --git a/Discussion/DiscussionTests/Presentation/DiscussionTopics/DiscussionSearchTopicsViewModelTests.swift b/Discussion/DiscussionTests/Presentation/DiscussionTopics/DiscussionSearchTopicsViewModelTests.swift index dedc8b85d..68a582509 100644 --- a/Discussion/DiscussionTests/Presentation/DiscussionTopics/DiscussionSearchTopicsViewModelTests.swift +++ b/Discussion/DiscussionTests/Presentation/DiscussionTopics/DiscussionSearchTopicsViewModelTests.swift @@ -2,10 +2,9 @@ // DiscussionSearchTopicsViewModelTests.swift // DiscussionTests // -// Created by  Stepanok Ivan on 24.02.2023. +// Created by Stepanok Ivan on 24.02.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Discussion @@ -19,12 +18,8 @@ final class DiscussionSearchTopicsViewModelTests: XCTestCase { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() let storage = CoreStorageMock() - let viewModel = DiscussionSearchTopicsViewModel(courseID: "123", - interactor: interactor, - storage: storage, - router: router, - debounce: .test) - + storage.useRelativeDates = false + let items = ThreadLists( threads: [ UserThread(id: "1", @@ -50,17 +45,22 @@ final class DiscussionSearchTopicsViewModelTests: XCTestCase { numPages: 1) ] ) - Given(storage, .useRelativeDates(getter: false)) - Given(interactor, .searchThreads(courseID: .any, searchText: .any, pageNumber: .any, willReturn: items)) + + interactor.searchThreadsHandler = { _, _, _ in items } + + let viewModel = DiscussionSearchTopicsViewModel(courseID: "123", + interactor: interactor, + storage: storage, + router: router, + debounce: .test) viewModel.searchText = "Test" - + // Wait for debounce + next event loop iteration try await Task.sleep(nanoseconds: UInt64(0.5 * Double(NSEC_PER_SEC))) await Task.yield() - Verify(interactor, .searchThreads(courseID: .any, searchText: .any, pageNumber: .any)) - + XCTAssertEqual(interactor.searchThreadsCallCount, 1) XCTAssertFalse(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) } @@ -68,70 +68,76 @@ final class DiscussionSearchTopicsViewModelTests: XCTestCase { func testSearchNoInternetError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() + let storage = CoreStorageMock() + storage.useRelativeDates = false + + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) + + interactor.searchThreadsHandler = { _, _, _ in throw noInternetError } + let viewModel = DiscussionSearchTopicsViewModel(courseID: "123", interactor: interactor, - storage: CoreStorageMock(), + storage: storage, router: router, debounce: .test) - - let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .searchThreads(courseID: .any, searchText: .any, pageNumber: .any, willThrow: noInternetError)) viewModel.searchText = "Test" - + // Wait for debounce + next event loop iteration try await Task.sleep(nanoseconds: UInt64(0.5 * Double(NSEC_PER_SEC))) await Task.yield() - Verify(interactor, .searchThreads(courseID: .any, searchText: .any, pageNumber: .any)) - + XCTAssertEqual(interactor.searchThreadsCallCount, 1) XCTAssertTrue(viewModel.showError) - XCTAssertTrue(viewModel.errorMessage == CoreLocalization.Error.slowOrNoInternetConnection) + XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertFalse(viewModel.fetchInProgress) } - + func testSearchUnknownError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() + let storage = CoreStorageMock() + storage.useRelativeDates = false + + interactor.searchThreadsHandler = { _, _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + let viewModel = DiscussionSearchTopicsViewModel(courseID: "123", interactor: interactor, - storage: CoreStorageMock(), + storage: storage, router: router, debounce: .test) - Given(interactor, .searchThreads(courseID: .any, searchText: .any, pageNumber: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - viewModel.searchText = "Test" - + // Wait for debounce + next event loop iteration try await Task.sleep(nanoseconds: UInt64(0.5 * Double(NSEC_PER_SEC))) await Task.yield() - Verify(interactor, .searchThreads(courseID: .any, searchText: .any, pageNumber: .any)) - + XCTAssertEqual(interactor.searchThreadsCallCount, 1) XCTAssertTrue(viewModel.showError) - XCTAssertTrue(viewModel.errorMessage == CoreLocalization.Error.unknownError) + XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertFalse(viewModel.fetchInProgress) } - + func testEmptyQuerySuccess() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() + let storage = CoreStorageMock() + storage.useRelativeDates = false + let viewModel = DiscussionSearchTopicsViewModel(courseID: "123", interactor: interactor, - storage: CoreStorageMock(), + storage: storage, router: router, debounce: .test) - + viewModel.searchText = "" - + // Wait for debounce + next event loop iteration try await Task.sleep(nanoseconds: UInt64(0.5 * Double(NSEC_PER_SEC))) await Task.yield() - Verify(interactor, 0, .searchThreads(courseID: .any, searchText: .any, pageNumber: .any)) - + XCTAssertEqual(interactor.searchThreadsCallCount, 0) XCTAssertFalse(viewModel.showError) XCTAssertFalse(viewModel.fetchInProgress) } diff --git a/Discussion/DiscussionTests/Presentation/DiscussionTopics/DiscussionTopicsViewModelTests.swift b/Discussion/DiscussionTests/Presentation/DiscussionTopics/DiscussionTopicsViewModelTests.swift index c82a4b63f..04f36babe 100644 --- a/Discussion/DiscussionTests/Presentation/DiscussionTopics/DiscussionTopicsViewModelTests.swift +++ b/Discussion/DiscussionTests/Presentation/DiscussionTopics/DiscussionTopicsViewModelTests.swift @@ -2,10 +2,9 @@ // DiscussionTopicsViewModelTests.swift // DiscussionTests // -// Created by  Stepanok Ivan on 31.01.2023. +// Created by Stepanok Ivan on 31.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Discussion @@ -14,7 +13,7 @@ import SwiftUI @MainActor final class DiscussionTopicsViewModelTests: XCTestCase { - + let topics = Topics(coursewareTopics: [ CoursewareTopics(id: "1", name: "1", threadListURL: "1", children: [ CoursewareTopics(id: "11", name: "11", threadListURL: "11", children: []) @@ -43,20 +42,21 @@ final class DiscussionTopicsViewModelTests: XCTestCase { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() let analytics = DiscussionAnalyticsMock() - let config = ConfigMock() + let config = ConfigProtocolMock() + + interactor.getTopicsHandler = { _ in self.topics } + interactor.getCourseDiscussionInfoHandler = { _ in self.discussionInfo } + let viewModel = DiscussionTopicsViewModel(title: "", interactor: interactor, router: router, analytics: analytics, config: config) - Given(interactor, .getTopics(courseID: .any, willReturn: topics)) - Given(interactor, .getCourseDiscussionInfo(courseID: .any, willReturn: discussionInfo)) - await viewModel.getTopics(courseID: "1") - Verify(interactor, .getTopics(courseID: .any)) - Verify(interactor, .getCourseDiscussionInfo(courseID: .any)) + XCTAssertEqual(interactor.getTopicsCallCount, 1) + XCTAssertEqual(interactor.getCourseDiscussionInfoCallCount, 1) XCTAssertNotNil(viewModel.topics) XCTAssertNotNil(viewModel.discussionTopics) @@ -64,52 +64,54 @@ final class DiscussionTopicsViewModelTests: XCTestCase { XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.isShowProgress) } - + func testGetTopicsNoInternetError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() let analytics = DiscussionAnalyticsMock() - let config = ConfigMock() + let config = ConfigProtocolMock() + + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) + + interactor.getTopicsHandler = { _ in throw noInternetError } + interactor.getCourseDiscussionInfoHandler = { _ in self.discussionInfo } + let viewModel = DiscussionTopicsViewModel(title: "", interactor: interactor, router: router, analytics: analytics, config: config) - let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .getTopics(courseID: .any, willThrow: noInternetError)) - Given(interactor, .getCourseDiscussionInfo(courseID: .any, willReturn: discussionInfo)) - await viewModel.getTopics(courseID: "1") - - Verify(interactor, .getCourseDiscussionInfo(courseID: .any)) - Verify(interactor, .getTopics(courseID: .any)) + + XCTAssertEqual(interactor.getCourseDiscussionInfoCallCount, 1) + XCTAssertEqual(interactor.getTopicsCallCount, 1) XCTAssertNil(viewModel.topics) XCTAssertNil(viewModel.discussionTopics) XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.isShowRefresh) } - + func testGetTopicsUnknownError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() let analytics = DiscussionAnalyticsMock() - let config = ConfigMock() + let config = ConfigProtocolMock() + + interactor.getTopicsHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + interactor.getCourseDiscussionInfoHandler = { _ in self.discussionInfo } + let viewModel = DiscussionTopicsViewModel(title: "", interactor: interactor, router: router, analytics: analytics, config: config) - - Given(interactor, .getTopics(courseID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - Given(interactor, .getCourseDiscussionInfo(courseID: .any, willReturn: discussionInfo)) await viewModel.getTopics(courseID: "1") - - Verify(interactor, .getCourseDiscussionInfo(courseID: .any)) - Verify(interactor, .getTopics(courseID: .any)) + + XCTAssertEqual(interactor.getCourseDiscussionInfoCallCount, 1) + XCTAssertEqual(interactor.getTopicsCallCount, 1) XCTAssertNil(viewModel.topics) XCTAssertNil(viewModel.discussionTopics) diff --git a/Discussion/DiscussionTests/Presentation/Posts/PostViewModelTests.swift b/Discussion/DiscussionTests/Presentation/Posts/PostViewModelTests.swift index c509bfea2..f101ef853 100644 --- a/Discussion/DiscussionTests/Presentation/Posts/PostViewModelTests.swift +++ b/Discussion/DiscussionTests/Presentation/Posts/PostViewModelTests.swift @@ -1,11 +1,10 @@ // -// DiscussionTests.swift +// PostViewModelTests.swift // DiscussionTests // -// Created by  Stepanok Ivan on 30.01.2023. +// Created by Stepanok Ivan on 30.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Discussion @@ -14,7 +13,7 @@ import SwiftUI @MainActor final class PostViewModelTests: XCTestCase { - + let threads = ThreadLists(threads: [ UserThread(id: "1", author: "1", @@ -103,22 +102,21 @@ final class PostViewModelTests: XCTestCase { ]) let discussionInfo = DiscussionInfo(discussionID: "1", blackouts: []) - + var interactor: DiscussionInteractorProtocolMock! var router: DiscussionRouterMock! - var config: ConfigMock! + var config: ConfigProtocolMock! var viewModel: PostsViewModel! - + override func setUp() async throws { try await super.setUp() - + interactor = DiscussionInteractorProtocolMock() router = DiscussionRouterMock() - config = ConfigMock() + config = ConfigProtocolMock() let storage = CoreStorageMock() + storage.useRelativeDates = false - Given(storage, .useRelativeDates(getter: false)) - viewModel = PostsViewModel( interactor: interactor, router: router, @@ -129,113 +127,100 @@ final class PostViewModelTests: XCTestCase { func testGetThreadListSuccess() async throws { var result = false - + viewModel.courseID = "1" viewModel.type = .allPosts - Given(interactor, .getThreadsList(courseID: .any, type: .any, sort: .any, filter: .any, page: .any, willReturn: threads)) - Given(interactor, .getCourseDiscussionInfo(courseID: .any, willReturn: discussionInfo)) + interactor.getThreadsListHandler = { _, _, _, _, _ in self.threads } + interactor.getCourseDiscussionInfoHandler = { _ in self.discussionInfo } viewModel.type = .allPosts result = await viewModel.getPosts(pageNumber: 1) XCTAssertTrue(result) result = false - + viewModel.type = .courseTopics(topicID: "") result = await viewModel.getPosts(pageNumber: 1) XCTAssertTrue(result) result = false - + viewModel.type = .followingPosts result = await viewModel.getPosts(pageNumber: 1) XCTAssertTrue(result) result = false - + viewModel.type = .nonCourseTopics result = await viewModel.getPosts(pageNumber: 1) XCTAssertTrue(result) - result = false - Verify(interactor, 4, .getThreadsList(courseID: .value("1"), type: .any, sort: .any, filter: .any, page: .value(1))) - + XCTAssertEqual(interactor.getThreadsListCallCount, 4) XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) } - + func testGetThreadListNoInternetError() async throws { var result = false - + viewModel.isBlackedOut = false let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - Given(interactor, .getThreadsList(courseID: .any, type: .any, sort: .any, filter: .any, page: .any, willThrow: noInternetError)) - Given(interactor, .getCourseDiscussionInfo(courseID: .any, willThrow: noInternetError)) + interactor.getThreadsListHandler = { _, _, _, _, _ in throw noInternetError } + interactor.getCourseDiscussionInfoHandler = { _ in throw noInternetError } viewModel.courseID = "1" viewModel.type = .allPosts result = await viewModel.getPosts(pageNumber: 1) - Verify(interactor, 1, .getThreadsList(courseID: .any, type: .any, sort: .any, filter: .any, page: .any)) - + XCTAssertEqual(interactor.getThreadsListCallCount, 1) XCTAssertFalse(result) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) } - + func testGetThreadListUnknownError() async throws { var result = false - + viewModel.isBlackedOut = false - Given(interactor, .getThreadsList(courseID: .any, type: .any, sort: .any, filter: .any, page: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - Given(interactor, .getCourseDiscussionInfo(courseID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) + interactor.getThreadsListHandler = { _, _, _, _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + interactor.getCourseDiscussionInfoHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } viewModel.courseID = "1" viewModel.type = .allPosts result = await viewModel.getPosts(pageNumber: 1) - Verify(interactor, 1, .getThreadsList(courseID: .any, type: .any, sort: .any, filter: .any, page: .any)) - + XCTAssertEqual(interactor.getThreadsListCallCount, 1) XCTAssertFalse(result) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) } - + func testSortingAndFilters() async throws { - - Given(interactor, .getThreadsList(courseID: .any, type: .any, sort: .any, filter: .any, page: .any, - willReturn: threads)) - Given(interactor, .getCourseDiscussionInfo(courseID: "1", willReturn: discussionInfo)) - + interactor.getThreadsListHandler = { _, _, _, _, _ in self.threads } + interactor.getCourseDiscussionInfoHandler = { _ in self.discussionInfo } + viewModel.courseID = "1" viewModel.type = .allPosts viewModel.sortTitle = .mostActivity _ = await viewModel.getPosts(pageNumber: 1) - XCTAssertTrue(viewModel.filteredPosts[0].title == "1") - - Given(interactor, .getThreadsList(courseID: .any, type: .any, sort: .value(.recentActivity), filter: .any, page: .any, - willReturn: threads)) - + XCTAssertEqual(viewModel.filteredPosts[0].title, "1") + viewModel.filterTitle = .unread viewModel.sortTitle = .recentActivity _ = await viewModel.getPosts(pageNumber: 1) - XCTAssertTrue(viewModel.filteredPosts[0].title == "1") + XCTAssertEqual(viewModel.filteredPosts[0].title, "1") XCTAssertNotNil(viewModel.filteredPosts.first(where: {$0.unreadCommentCount == 4})) - - Given(interactor, .getThreadsList(courseID: .any, type: .any, sort: .value(.mostVotes), filter: .any, page: .any, - willReturn: threads)) - + viewModel.filterTitle = .unanswered viewModel.sortTitle = .mostVotes _ = await viewModel.getPosts(pageNumber: 1) - XCTAssertTrue(viewModel.filteredPosts[0].title == "1") + XCTAssertEqual(viewModel.filteredPosts[0].title, "1") XCTAssertNotNil(viewModel.filteredPosts.first(where: { $0.hasEndorsed })) - - Verify(interactor, .getThreadsList(courseID: .any, type: .any, sort: .any, filter: .any, page: .any)) - } + XCTAssertTrue(interactor.getThreadsListCallCount > 0) + } } diff --git a/Discussion/DiscussionTests/Presentation/Responses/ResponsesViewModelTests.swift b/Discussion/DiscussionTests/Presentation/Responses/ResponsesViewModelTests.swift index af9726e3c..8251ddccc 100644 --- a/Discussion/DiscussionTests/Presentation/Responses/ResponsesViewModelTests.swift +++ b/Discussion/DiscussionTests/Presentation/Responses/ResponsesViewModelTests.swift @@ -2,10 +2,9 @@ // ResponsesViewModelTests.swift // DiscussionTests // -// Created by  Stepanok Ivan on 31.01.2023. +// Created by Stepanok Ivan on 31.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Discussion @@ -14,7 +13,7 @@ import SwiftUI @MainActor final class ResponsesViewModelTests: XCTestCase { - + let userComments = [ UserComment(authorName: "1", authorAvatar: "1", @@ -62,7 +61,7 @@ final class ResponsesViewModelTests: XCTestCase { parentID: nil, abuseFlagged: false) ] - + let post = Post(authorName: "1", authorAvatar: "1", postDate: Date(), @@ -103,9 +102,13 @@ final class ResponsesViewModelTests: XCTestCase { func testGetCommentsSuccess() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() var result = false + interactor.getCommentResponsesHandler = { _, _ in + (self.userComments, Pagination(next: "", previous: "", count: 1, numPages: 1)) + } + let viewModel = ResponsesViewModel(courseID: "courseID", interactor: interactor, router: router, @@ -113,29 +116,27 @@ final class ResponsesViewModelTests: XCTestCase { storage: CoreStorageMock(), threadStateSubject: .init(.postAdded(id: "1")), analytics: DiscussionAnalyticsMock()) - - Given(interactor, .getCommentResponses(commentID: .any, page: .any, - willReturn: (userComments, Pagination(next: "", - previous: "", - count: 1, - numPages: 1)))) - + result = await viewModel.getResponsesData(commentID: "1", parentComment: post, page: 1) - - Verify(interactor, .getCommentResponses(commentID: .any, page: .any)) - + + XCTAssertEqual(interactor.getCommentResponsesCallCount, 1) + XCTAssertTrue(result) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.isShowProgress) } - + func testGetCommentsNoInternetError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() var result = false + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) + + interactor.getCommentResponsesHandler = { _, _ in throw noInternetError } + let viewModel = ResponsesViewModel(courseID: "courseID", interactor: interactor, router: router, @@ -143,28 +144,26 @@ final class ResponsesViewModelTests: XCTestCase { storage: CoreStorageMock(), threadStateSubject: .init(.postAdded(id: "1")), analytics: DiscussionAnalyticsMock()) - - let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .getCommentResponses(commentID: .any, page: .any, willThrow: noInternetError)) - + result = await viewModel.getResponsesData(commentID: "1", parentComment: post, page: 1) - - Verify(interactor, .getCommentResponses(commentID: .any, page: .any)) - + + XCTAssertEqual(interactor.getCommentResponsesCallCount, 1) + XCTAssertFalse(result) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) XCTAssertNotNil(viewModel.errorMessage) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) } - + func testGetCommentsUnknownError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() var result = false + interactor.getCommentResponsesHandler = { _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + let viewModel = ResponsesViewModel(courseID: "courseID", interactor: interactor, router: router, @@ -172,13 +171,11 @@ final class ResponsesViewModelTests: XCTestCase { storage: CoreStorageMock(), threadStateSubject: .init(.postAdded(id: "1")), analytics: DiscussionAnalyticsMock()) - - Given(interactor, .getCommentResponses(commentID: .any, page: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + result = await viewModel.getResponsesData(commentID: "1", parentComment: post, page: 1) - - Verify(interactor, .getCommentResponses(commentID: .any, page: .any)) - + + XCTAssertEqual(interactor.getCommentResponsesCallCount, 1) + XCTAssertFalse(result) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) @@ -189,7 +186,9 @@ final class ResponsesViewModelTests: XCTestCase { func testPostCommentSuccess() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() + + interactor.addCommentToHandler = { _, _, _ in self.post } let viewModel = ResponsesViewModel(courseID: "courseID", interactor: interactor, @@ -198,22 +197,24 @@ final class ResponsesViewModelTests: XCTestCase { storage: CoreStorageMock(), threadStateSubject: .init(.postAdded(id: "1")), analytics: DiscussionAnalyticsMock()) - - Given(interactor, .addCommentTo(threadID: .any, rawBody: .any, parentID: .any, willReturn: post)) - + await viewModel.postComment(threadID: "1", rawBody: "1", parentID: nil) - - Verify(interactor, .addCommentTo(threadID: .any, rawBody: .any, parentID: .any)) - + + XCTAssertEqual(interactor.addCommentToCallCount, 1) + XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) XCTAssertFalse(viewModel.isShowProgress) } - + func testPostCommentNoInternetError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() + + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) + + interactor.addCommentToHandler = { _, _, _ in throw noInternetError } let viewModel = ResponsesViewModel(courseID: "courseID", interactor: interactor, @@ -222,24 +223,22 @@ final class ResponsesViewModelTests: XCTestCase { storage: CoreStorageMock(), threadStateSubject: .init(.postAdded(id: "1")), analytics: DiscussionAnalyticsMock()) - - let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .addCommentTo(threadID: .any, rawBody: .any, parentID: .any, willThrow: noInternetError)) - + await viewModel.postComment(threadID: "1", rawBody: "1", parentID: nil) - - Verify(interactor, .addCommentTo(threadID: .any, rawBody: .any, parentID: .any)) - + + XCTAssertEqual(interactor.addCommentToCallCount, 1) + XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) } - + func testPostCommentUnknownError() async throws { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() + + interactor.addCommentToHandler = { _, _, _ in throw NSError(domain: "error", code: -1, userInfo: nil) } let viewModel = ResponsesViewModel(courseID: "courseID", interactor: interactor, @@ -248,22 +247,24 @@ final class ResponsesViewModelTests: XCTestCase { storage: CoreStorageMock(), threadStateSubject: .init(.postAdded(id: "1")), analytics: DiscussionAnalyticsMock()) - - Given(interactor, .addCommentTo(threadID: .any, rawBody: .any, parentID: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) await viewModel.postComment(threadID: "1", rawBody: "1", parentID: nil) - - Verify(interactor, .addCommentTo(threadID: .any, rawBody: .any, parentID: .any)) - + + XCTAssertEqual(interactor.addCommentToCallCount, 1) + XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) } - + func testFetchMorePosts() async { let interactor = DiscussionInteractorProtocolMock() let router = DiscussionRouterMock() - let config = ConfigMock() + let config = ConfigProtocolMock() + + interactor.getCommentResponsesHandler = { _, _ in + (self.userComments, Pagination(next: "", previous: "", count: 1, numPages: 1)) + } let viewModel = ResponsesViewModel(courseID: "courseID", interactor: interactor, @@ -272,20 +273,14 @@ final class ResponsesViewModelTests: XCTestCase { storage: CoreStorageMock(), threadStateSubject: .init(.postAdded(id: "1")), analytics: DiscussionAnalyticsMock()) - + viewModel.totalPages = 2 viewModel.comments = userComments - - Given(interactor, .getCommentResponses(commentID: .any, page: .any, - willReturn: (userComments, Pagination(next: "", - previous: "", - count: 1, - numPages: 1)))) - + await viewModel.fetchMorePosts(commentID: "1", parentComment: post, index: 0) - - Verify(interactor, .getCommentResponses(commentID: .any, page: .any)) - + + XCTAssertEqual(interactor.getCommentResponsesCallCount, 1) + XCTAssertEqual(viewModel.comments.count, (userComments + userComments).count) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) diff --git a/Discussion/Mockfile b/Discussion/Mockfile deleted file mode 100644 index b7eb63e2f..000000000 --- a/Discussion/Mockfile +++ /dev/null @@ -1,18 +0,0 @@ -sourceryCommand: mint run krzysztofzablocki/Sourcery@2.1.2 sourcery -sourceryTemplate: ../MockTemplate.swifttemplate -unit.tests.mock: - sources: - include: - - ./../Core - - ./Discussion - exclude: [] - output: ./DiscussionTests/DiscussionMock.generated.swift - targets: - - MyAppUnitTests - import: - - Core - - Discussion - - Foundation - - SwiftUI - - Combine - - OEXFoundation \ No newline at end of file diff --git a/Documentation/Documentation.md b/Documentation/Documentation.md index 81c24d4c5..2fb33c562 100644 --- a/Documentation/Documentation.md +++ b/Documentation/Documentation.md @@ -230,6 +230,6 @@ The following technologies are used in the project: - CoreData, data persistence. - Firebase, infrastructure. - XCTest, unit testing framework. -- SwiftyMocky, framework for automatic mock generation. +- Mockolo, framework for automatic mock generation. - SwiftLint, a tool to enforce Swift style and conventions. - SwiftGen, the Swift code generator for assets. diff --git a/Downloads/Downloads.xcodeproj/project.pbxproj b/Downloads/Downloads.xcodeproj/project.pbxproj index 410444bc5..7edc1d020 100644 --- a/Downloads/Downloads.xcodeproj/project.pbxproj +++ b/Downloads/Downloads.xcodeproj/project.pbxproj @@ -34,7 +34,7 @@ CEB36E422D6A0E2C00907A89 /* swiftgen.yml in Resources */ = {isa = PBXBuildFile; fileRef = CEB36E412D6A0E2C00907A89 /* swiftgen.yml */; }; CEB36E562D6A2A0400907A89 /* Core.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEB36E552D6A2A0400907A89 /* Core.framework */; }; CEB36E5A2D6A2B9900907A89 /* OEXFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CEB36E592D6A2B9900907A89 /* OEXFoundation */; }; - CEC873C02D75E15C00A2626C /* Downloads Mock.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC873BF2D75E15C00A2626C /* Downloads Mock.generated.swift */; }; + CEC873C02D75E15C00A2626C /* DownloadsMocks.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC873BF2D75E15C00A2626C /* DownloadsMocks.generated.swift */; }; EDE11E2D4D726D34775CF243 /* Pods_App_Downloads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE4EC0036E64DA88BB2D053F /* Pods_App_Downloads.framework */; }; /* End PBXBuildFile section */ @@ -102,7 +102,7 @@ CEB36E3E2D6A0DE800907A89 /* DownloadsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadsTests.swift; sourceTree = ""; }; CEB36E412D6A0E2C00907A89 /* swiftgen.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = swiftgen.yml; sourceTree = ""; }; CEB36E552D6A2A0400907A89 /* Core.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Core.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - CEC873BF2D75E15C00A2626C /* Downloads Mock.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Downloads Mock.generated.swift"; sourceTree = ""; }; + CEC873BF2D75E15C00A2626C /* DownloadsMocks.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadsMocks.generated.swift; sourceTree = ""; }; F88F26577D0F66933184E825 /* Pods-App-Downloads.debugprod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Downloads.debugprod.xcconfig"; path = "Target Support Files/Pods-App-Downloads/Pods-App-Downloads.debugprod.xcconfig"; sourceTree = ""; }; FA71B94B494DEAD479651F27 /* Pods-App-Downloads.releasestage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Downloads.releasestage.xcconfig"; path = "Target Support Files/Pods-App-Downloads/Pods-App-Downloads.releasestage.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -269,12 +269,20 @@ CEB36E3F2D6A0DE800907A89 /* DownloadsTests */ = { isa = PBXGroup; children = ( + CEC873C12D75E15C00A2626C /* Generated */, CEB36E3E2D6A0DE800907A89 /* DownloadsTests.swift */, - CEC873BF2D75E15C00A2626C /* Downloads Mock.generated.swift */, ); path = DownloadsTests; sourceTree = ""; }; + CEC873C12D75E15C00A2626C /* Generated */ = { + isa = PBXGroup; + children = ( + CEC873BF2D75E15C00A2626C /* DownloadsMocks.generated.swift */, + ); + path = Generated; + sourceTree = ""; + }; FA6696D1625DF71CF1ED8DD8 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -330,7 +338,6 @@ CEB36E0D2D6A0D0B00907A89 /* Sources */, CEB36E0E2D6A0D0B00907A89 /* Frameworks */, CEB36E0F2D6A0D0B00907A89 /* Resources */, - 221FEA57FF59FA75CEF68692 /* [CP] Copy Pods Resources */, CEB36E5C2D6A2B9900907A89 /* Embed Frameworks */, ); buildRules = ( @@ -426,23 +433,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 221FEA57FF59FA75CEF68692 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Downloads-DownloadsTests/Pods-App-Downloads-DownloadsTests-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Downloads-DownloadsTests/Pods-App-Downloads-DownloadsTests-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App-Downloads-DownloadsTests/Pods-App-Downloads-DownloadsTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; A0943E23063B85F2D8D788FE /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -515,7 +505,7 @@ buildActionMask = 2147483647; files = ( CEB36E402D6A0DE800907A89 /* DownloadsTests.swift in Sources */, - CEC873C02D75E15C00A2626C /* Downloads Mock.generated.swift in Sources */, + CEC873C02D75E15C00A2626C /* DownloadsMocks.generated.swift in Sources */, CE8648942DA575DF00821EC9 /* DownloadCoursePreviewModel.xcdatamodeld in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Downloads/Downloads/Domain/DownloadsHelperProtocol.swift b/Downloads/Downloads/Domain/DownloadsHelperProtocol.swift index 79cafb19e..e2919bf3c 100644 --- a/Downloads/Downloads/Domain/DownloadsHelperProtocol.swift +++ b/Downloads/Downloads/Domain/DownloadsHelperProtocol.swift @@ -8,7 +8,7 @@ import Foundation import Core -//sourcery: AutoMockable +/// @mockable public protocol DownloadsHelperProtocol: Sendable { func calculateDownloadProgress(courseID: String) async -> (downloaded: Int, total: Int) func isDownloading(courseID: String) async -> Bool @@ -17,7 +17,7 @@ public protocol DownloadsHelperProtocol: Sendable { } #if DEBUG -public actor DownloadsHelperMock: DownloadsHelperProtocol { +public actor DownloadsHelperPreviewMock: DownloadsHelperProtocol { public var mockDownloadProgress: (downloaded: Int, total: Int) = (0, 0) public var mockIsDownloading: Bool = false diff --git a/Downloads/Downloads/Domain/DownloadsInteractor.swift b/Downloads/Downloads/Domain/DownloadsInteractor.swift index d8710593f..f63f0cdd9 100644 --- a/Downloads/Downloads/Domain/DownloadsInteractor.swift +++ b/Downloads/Downloads/Domain/DownloadsInteractor.swift @@ -8,7 +8,7 @@ import Foundation import Core -//sourcery: AutoMockable +/// @mockable public protocol DownloadsInteractorProtocol: Sendable { func getDownloadCourses() async throws -> [DownloadCoursePreview] func getDownloadCoursesOffline() async throws -> [DownloadCoursePreview] diff --git a/Downloads/Downloads/Presentation/AppDownloadsViewModel.swift b/Downloads/Downloads/Presentation/AppDownloadsViewModel.swift index 79696e030..4e5489dd5 100644 --- a/Downloads/Downloads/Presentation/AppDownloadsViewModel.swift +++ b/Downloads/Downloads/Presentation/AppDownloadsViewModel.swift @@ -780,10 +780,10 @@ public extension AppDownloadsViewModel { courseManager: CourseStructureManagerMock(), downloadManager: DownloadManagerMock(), connectivity: Connectivity(config: ConfigMock()), - downloadsHelper: DownloadsHelperMock(), + downloadsHelper: DownloadsHelperPreviewMock(), router: DownloadsRouterMock(), storage: DownloadsStorageMock(), - analytics: DownloadsAnalyticsMock() + analytics: DownloadsAnalyticsPreviewMock() ) } #endif diff --git a/Downloads/Downloads/Presentation/DownloadsAnalytics.swift b/Downloads/Downloads/Presentation/DownloadsAnalytics.swift index d976787a5..7ddbe4843 100644 --- a/Downloads/Downloads/Presentation/DownloadsAnalytics.swift +++ b/Downloads/Downloads/Presentation/DownloadsAnalytics.swift @@ -8,7 +8,7 @@ import Foundation import Core -//sourcery: AutoMockable +/// @mockable public protocol DownloadsAnalytics { func downloadCourseClicked(courseId: String, courseName: String) func cancelDownloadClicked(courseId: String, courseName: String) @@ -30,7 +30,7 @@ public enum AnalyticsError: String { } #if DEBUG -public class DownloadsAnalyticsMock: DownloadsAnalytics { +public class DownloadsAnalyticsPreviewMock: DownloadsAnalytics { public init() {} public func downloadCourseClicked(courseId: String, courseName: String) {} diff --git a/Downloads/DownloadsTests/Downloads Mock.generated.swift b/Downloads/DownloadsTests/Downloads Mock.generated.swift deleted file mode 100644 index 3b877c26c..000000000 --- a/Downloads/DownloadsTests/Downloads Mock.generated.swift +++ /dev/null @@ -1,5451 +0,0 @@ -// Generated using Sourcery 2.1.2 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT - - -// Generated with SwiftyMocky 4.2.0 -// Required Sourcery: 1.8.0 - - -import SwiftyMocky -import XCTest -import Core -import Downloads -import Foundation -import SwiftUI -import Combine -import OEXFoundation - - -// MARK: - AuthInteractorProtocol - -open class AuthInteractorProtocolMock: AuthInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - @discardableResult - open func login(username: String, password: String) throws -> User { - addInvocation(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) - let perform = methodPerformValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) as? (String, String) -> Void - perform?(`username`, `password`) - var __value: User - do { - __value = try methodReturnValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(username: String, password: String). Use given") - Failure("Stub return value not specified for login(username: String, password: String). Use given") - } catch { - throw error - } - return __value - } - - @discardableResult - open func login(externalToken: String, backend: String) throws -> User { - addInvocation(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) - let perform = methodPerformValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) as? (String, String) -> Void - perform?(`externalToken`, `backend`) - var __value: User - do { - __value = try methodReturnValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - Failure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - } catch { - throw error - } - return __value - } - - open func login(ssoToken: String) throws -> User { - addInvocation(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) - let perform = methodPerformValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) as? (String) -> Void - perform?(`ssoToken`) - var __value: User - do { - __value = try methodReturnValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(ssoToken: String). Use given") - Failure("Stub return value not specified for login(ssoToken: String). Use given") - } catch { - throw error - } - return __value - } - - open func resetPassword(email: String) throws -> ResetPassword { - addInvocation(.m_resetPassword__email_email(Parameter.value(`email`))) - let perform = methodPerformValue(.m_resetPassword__email_email(Parameter.value(`email`))) as? (String) -> Void - perform?(`email`) - var __value: ResetPassword - do { - __value = try methodReturnValue(.m_resetPassword__email_email(Parameter.value(`email`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for resetPassword(email: String). Use given") - Failure("Stub return value not specified for resetPassword(email: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCookies(force: Bool) throws { - addInvocation(.m_getCookies__force_force(Parameter.value(`force`))) - let perform = methodPerformValue(.m_getCookies__force_force(Parameter.value(`force`))) as? (Bool) -> Void - perform?(`force`) - do { - _ = try methodReturnValue(.m_getCookies__force_force(Parameter.value(`force`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getRegistrationFields() throws -> [PickerFields] { - addInvocation(.m_getRegistrationFields) - let perform = methodPerformValue(.m_getRegistrationFields) as? () -> Void - perform?() - var __value: [PickerFields] - do { - __value = try methodReturnValue(.m_getRegistrationFields).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getRegistrationFields(). Use given") - Failure("Stub return value not specified for getRegistrationFields(). Use given") - } catch { - throw error - } - return __value - } - - open func registerUser(fields: [String: String], isSocial: Bool) throws -> User { - addInvocation(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) - let perform = methodPerformValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) as? ([String: String], Bool) -> Void - perform?(`fields`, `isSocial`) - var __value: User - do { - __value = try methodReturnValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - Failure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - } catch { - throw error - } - return __value - } - - open func validateRegistrationFields(fields: [String: String]) throws -> [String: String] { - addInvocation(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) - let perform = methodPerformValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) as? ([String: String]) -> Void - perform?(`fields`) - var __value: [String: String] - do { - __value = try methodReturnValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - Failure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_login__username_usernamepassword_password(Parameter, Parameter) - case m_login__externalToken_externalTokenbackend_backend(Parameter, Parameter) - case m_login__ssoToken_ssoToken(Parameter) - case m_resetPassword__email_email(Parameter) - case m_getCookies__force_force(Parameter) - case m_getRegistrationFields - case m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>, Parameter) - case m_validateRegistrationFields__fields_fields(Parameter<[String: String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_login__username_usernamepassword_password(let lhsUsername, let lhsPassword), .m_login__username_usernamepassword_password(let rhsUsername, let rhsPassword)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsername, rhs: rhsUsername, with: matcher), lhsUsername, rhsUsername, "username")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPassword, rhs: rhsPassword, with: matcher), lhsPassword, rhsPassword, "password")) - return Matcher.ComparisonResult(results) - - case (.m_login__externalToken_externalTokenbackend_backend(let lhsExternaltoken, let lhsBackend), .m_login__externalToken_externalTokenbackend_backend(let rhsExternaltoken, let rhsBackend)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsExternaltoken, rhs: rhsExternaltoken, with: matcher), lhsExternaltoken, rhsExternaltoken, "externalToken")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBackend, rhs: rhsBackend, with: matcher), lhsBackend, rhsBackend, "backend")) - return Matcher.ComparisonResult(results) - - case (.m_login__ssoToken_ssoToken(let lhsSsotoken), .m_login__ssoToken_ssoToken(let rhsSsotoken)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSsotoken, rhs: rhsSsotoken, with: matcher), lhsSsotoken, rhsSsotoken, "ssoToken")) - return Matcher.ComparisonResult(results) - - case (.m_resetPassword__email_email(let lhsEmail), .m_resetPassword__email_email(let rhsEmail)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEmail, rhs: rhsEmail, with: matcher), lhsEmail, rhsEmail, "email")) - return Matcher.ComparisonResult(results) - - case (.m_getCookies__force_force(let lhsForce), .m_getCookies__force_force(let rhsForce)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsForce, rhs: rhsForce, with: matcher), lhsForce, rhsForce, "force")) - return Matcher.ComparisonResult(results) - - case (.m_getRegistrationFields, .m_getRegistrationFields): return .match - - case (.m_registerUser__fields_fieldsisSocial_isSocial(let lhsFields, let lhsIssocial), .m_registerUser__fields_fieldsisSocial_isSocial(let rhsFields, let rhsIssocial)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIssocial, rhs: rhsIssocial, with: matcher), lhsIssocial, rhsIssocial, "isSocial")) - return Matcher.ComparisonResult(results) - - case (.m_validateRegistrationFields__fields_fields(let lhsFields), .m_validateRegistrationFields__fields_fields(let rhsFields)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_login__username_usernamepassword_password(p0, p1): return p0.intValue + p1.intValue - case let .m_login__externalToken_externalTokenbackend_backend(p0, p1): return p0.intValue + p1.intValue - case let .m_login__ssoToken_ssoToken(p0): return p0.intValue - case let .m_resetPassword__email_email(p0): return p0.intValue - case let .m_getCookies__force_force(p0): return p0.intValue - case .m_getRegistrationFields: return 0 - case let .m_registerUser__fields_fieldsisSocial_isSocial(p0, p1): return p0.intValue + p1.intValue - case let .m_validateRegistrationFields__fields_fields(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_login__username_usernamepassword_password: return ".login(username:password:)" - case .m_login__externalToken_externalTokenbackend_backend: return ".login(externalToken:backend:)" - case .m_login__ssoToken_ssoToken: return ".login(ssoToken:)" - case .m_resetPassword__email_email: return ".resetPassword(email:)" - case .m_getCookies__force_force: return ".getCookies(force:)" - case .m_getRegistrationFields: return ".getRegistrationFields()" - case .m_registerUser__fields_fieldsisSocial_isSocial: return ".registerUser(fields:isSocial:)" - case .m_validateRegistrationFields__fields_fields: return ".validateRegistrationFields(fields:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - @discardableResult - public static func login(username: Parameter, password: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func login(ssoToken: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func resetPassword(email: Parameter, willReturn: ResetPassword...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getRegistrationFields(willReturn: [PickerFields]...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willReturn: [String: String]...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func login(ssoToken: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func login(ssoToken: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func resetPassword(email: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resetPassword(email: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (ResetPassword).self) - willProduce(stubber) - return given - } - public static func getCookies(force: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCookies(force: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func getRegistrationFields(willThrow: Error...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getRegistrationFields(willProduce: (StubberThrows<[PickerFields]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([PickerFields]).self) - willProduce(stubber) - return given - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willProduce: (StubberThrows<[String: String]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([String: String]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - @discardableResult - public static func login(username: Parameter, password: Parameter) -> Verify { return Verify(method: .m_login__username_usernamepassword_password(`username`, `password`))} - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter) -> Verify { return Verify(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`))} - public static func login(ssoToken: Parameter) -> Verify { return Verify(method: .m_login__ssoToken_ssoToken(`ssoToken`))} - public static func resetPassword(email: Parameter) -> Verify { return Verify(method: .m_resetPassword__email_email(`email`))} - public static func getCookies(force: Parameter) -> Verify { return Verify(method: .m_getCookies__force_force(`force`))} - public static func getRegistrationFields() -> Verify { return Verify(method: .m_getRegistrationFields)} - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter) -> Verify { return Verify(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`))} - public static func validateRegistrationFields(fields: Parameter<[String: String]>) -> Verify { return Verify(method: .m_validateRegistrationFields__fields_fields(`fields`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - @discardableResult - public static func login(username: Parameter, password: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__username_usernamepassword_password(`username`, `password`), performs: perform) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), performs: perform) - } - public static func login(ssoToken: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_login__ssoToken_ssoToken(`ssoToken`), performs: perform) - } - public static func resetPassword(email: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_resetPassword__email_email(`email`), performs: perform) - } - public static func getCookies(force: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_getCookies__force_force(`force`), performs: perform) - } - public static func getRegistrationFields(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getRegistrationFields, performs: perform) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, perform: @escaping ([String: String], Bool) -> Void) -> Perform { - return Perform(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), performs: perform) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, perform: @escaping ([String: String]) -> Void) -> Perform { - return Perform(method: .m_validateRegistrationFields__fields_fields(`fields`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - BaseRouter -@MainActor -open class BaseRouterMock: BaseRouter, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func backToRoot(animated: Bool) { - addInvocation(.m_backToRoot__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_backToRoot__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func back(animated: Bool) { - addInvocation(.m_back__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_back__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func backWithFade() { - addInvocation(.m_backWithFade) - let perform = methodPerformValue(.m_backWithFade) as? () -> Void - perform?() - } - - open func dismiss(animated: Bool) { - addInvocation(.m_dismiss__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_dismiss__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func removeLastView(controllers: Int) { - addInvocation(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) - let perform = methodPerformValue(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) as? (Int) -> Void - perform?(`controllers`) - } - - open func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { - addInvocation(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) - let perform = methodPerformValue(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) as? (LogistrationSourceScreen, PostLoginData?) -> Void - perform?(`sourceScreen`, `postLoginData`) - } - - open func showStartupScreen() { - addInvocation(.m_showStartupScreen) - let perform = methodPerformValue(.m_showStartupScreen) as? () -> Void - perform?() - } - - open func showLoginScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showForgotPasswordScreen() { - addInvocation(.m_showForgotPasswordScreen) - let perform = methodPerformValue(.m_showForgotPasswordScreen) as? () -> Void - perform?() - } - - open func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) as? (String?, LogistrationSourceScreen) -> Void - perform?(`searchQuery`, `sourceScreen`) - } - - open func showWebBrowser(title: String, url: URL) { - addInvocation(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) - let perform = methodPerformValue(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) as? (String, URL) -> Void - perform?(`title`, `url`) - } - - open func showSSOWebBrowser(title: String) { - addInvocation(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) - let perform = methodPerformValue(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) as? (String) -> Void - perform?(`title`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) as? (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void - perform?(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) as? (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void - perform?(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { - addInvocation(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) as? (UIModalTransitionStyle, any View, (() -> Void)?) -> Void - perform?(`transitionStyle`, `view`, `completion`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { - addInvocation(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) as? (UIModalTransitionStyle, Bool, () -> any View) -> Void - perform?(`transitionStyle`, `animated`, `content`) - } - - - fileprivate enum MethodType { - case m_backToRoot__animated_animated(Parameter) - case m_back__animated_animated(Parameter) - case m_backWithFade - case m_dismiss__animated_animated(Parameter) - case m_removeLastView__controllers_controllers(Parameter) - case m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter, Parameter) - case m_showStartupScreen - case m_showLoginScreen__sourceScreen_sourceScreen(Parameter) - case m_showRegisterScreen__sourceScreen_sourceScreen(Parameter) - case m_showForgotPasswordScreen - case m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter, Parameter) - case m_showWebBrowser__title_titleurl_url(Parameter, Parameter) - case m_showSSOWebBrowser__title_title(Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter<() -> Void>) - case m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter, Parameter, Parameter<(() -> Void)?>) - case m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter, Parameter, Parameter<() -> any View>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_backToRoot__animated_animated(let lhsAnimated), .m_backToRoot__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_back__animated_animated(let lhsAnimated), .m_back__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_backWithFade, .m_backWithFade): return .match - - case (.m_dismiss__animated_animated(let lhsAnimated), .m_dismiss__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_removeLastView__controllers_controllers(let lhsControllers), .m_removeLastView__controllers_controllers(let rhsControllers)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsControllers, rhs: rhsControllers, with: matcher), lhsControllers, rhsControllers, "controllers")) - return Matcher.ComparisonResult(results) - - case (.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let lhsSourcescreen, let lhsPostlogindata), .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let rhsSourcescreen, let rhsPostlogindata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPostlogindata, rhs: rhsPostlogindata, with: matcher), lhsPostlogindata, rhsPostlogindata, "postLoginData")) - return Matcher.ComparisonResult(results) - - case (.m_showStartupScreen, .m_showStartupScreen): return .match - - case (.m_showLoginScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showLoginScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showRegisterScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showRegisterScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showForgotPasswordScreen, .m_showForgotPasswordScreen): return .match - - case (.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let lhsSearchquery, let lhsSourcescreen), .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let rhsSearchquery, let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchquery, rhs: rhsSearchquery, with: matcher), lhsSearchquery, rhsSearchquery, "searchQuery")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showWebBrowser__title_titleurl_url(let lhsTitle, let lhsUrl), .m_showWebBrowser__title_titleurl_url(let rhsTitle, let rhsUrl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - return Matcher.ComparisonResult(results) - - case (.m_showSSOWebBrowser__title_title(let lhsTitle), .m_showSSOWebBrowser__title_title(let rhsTitle)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let lhsAlerttitle, let lhsAlertmessage, let lhsPositiveaction, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsType), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let rhsAlerttitle, let rhsAlertmessage, let rhsPositiveaction, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPositiveaction, rhs: rhsPositiveaction, with: matcher), lhsPositiveaction, rhsPositiveaction, "positiveAction")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let lhsAlerttitle, let lhsAlertmessage, let lhsNextsectionname, let lhsAction, let lhsImage, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsNextsectiontapped), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let rhsAlerttitle, let rhsAlertmessage, let rhsNextsectionname, let rhsAction, let rhsImage, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsNextsectiontapped)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectionname, rhs: rhsNextsectionname, with: matcher), lhsNextsectionname, rhsNextsectionname, "nextSectionName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsImage, rhs: rhsImage, with: matcher), lhsImage, rhsImage, "image")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectiontapped, rhs: rhsNextsectiontapped, with: matcher), lhsNextsectiontapped, rhsNextsectiontapped, "nextSectionTapped")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let lhsTransitionstyle, let lhsView, let lhsCompletion), .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let rhsTransitionstyle, let rhsView, let rhsCompletion)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsView, rhs: rhsView, with: matcher), lhsView, rhsView, "view")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCompletion, rhs: rhsCompletion, with: matcher), lhsCompletion, rhsCompletion, "completion")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let lhsTransitionstyle, let lhsAnimated, let lhsContent), .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let rhsTransitionstyle, let rhsAnimated, let rhsContent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsContent, rhs: rhsContent, with: matcher), lhsContent, rhsContent, "content")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_backToRoot__animated_animated(p0): return p0.intValue - case let .m_back__animated_animated(p0): return p0.intValue - case .m_backWithFade: return 0 - case let .m_dismiss__animated_animated(p0): return p0.intValue - case let .m_removeLastView__controllers_controllers(p0): return p0.intValue - case let .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(p0, p1): return p0.intValue + p1.intValue - case .m_showStartupScreen: return 0 - case let .m_showLoginScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case let .m_showRegisterScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case .m_showForgotPasswordScreen: return 0 - case let .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(p0, p1): return p0.intValue + p1.intValue - case let .m_showWebBrowser__title_titleurl_url(p0, p1): return p0.intValue + p1.intValue - case let .m_showSSOWebBrowser__title_title(p0): return p0.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(p0, p1, p2, p3, p4, p5, p6, p7): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue + p7.intValue - case let .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_backToRoot__animated_animated: return ".backToRoot(animated:)" - case .m_back__animated_animated: return ".back(animated:)" - case .m_backWithFade: return ".backWithFade()" - case .m_dismiss__animated_animated: return ".dismiss(animated:)" - case .m_removeLastView__controllers_controllers: return ".removeLastView(controllers:)" - case .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData: return ".showMainOrWhatsNewScreen(sourceScreen:postLoginData:)" - case .m_showStartupScreen: return ".showStartupScreen()" - case .m_showLoginScreen__sourceScreen_sourceScreen: return ".showLoginScreen(sourceScreen:)" - case .m_showRegisterScreen__sourceScreen_sourceScreen: return ".showRegisterScreen(sourceScreen:)" - case .m_showForgotPasswordScreen: return ".showForgotPasswordScreen()" - case .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen: return ".showDiscoveryScreen(searchQuery:sourceScreen:)" - case .m_showWebBrowser__title_titleurl_url: return ".showWebBrowser(title:url:)" - case .m_showSSOWebBrowser__title_title: return ".showSSOWebBrowser(title:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type: return ".presentAlert(alertTitle:alertMessage:positiveAction:onCloseTapped:firstButtonTapped:type:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped: return ".presentAlert(alertTitle:alertMessage:nextSectionName:action:image:onCloseTapped:firstButtonTapped:nextSectionTapped:)" - case .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion: return ".presentView(transitionStyle:view:completion:)" - case .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content: return ".presentView(transitionStyle:animated:content:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func backToRoot(animated: Parameter) -> Verify { return Verify(method: .m_backToRoot__animated_animated(`animated`))} - public static func back(animated: Parameter) -> Verify { return Verify(method: .m_back__animated_animated(`animated`))} - public static func backWithFade() -> Verify { return Verify(method: .m_backWithFade)} - public static func dismiss(animated: Parameter) -> Verify { return Verify(method: .m_dismiss__animated_animated(`animated`))} - public static func removeLastView(controllers: Parameter) -> Verify { return Verify(method: .m_removeLastView__controllers_controllers(`controllers`))} - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter) -> Verify { return Verify(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`))} - public static func showStartupScreen() -> Verify { return Verify(method: .m_showStartupScreen)} - public static func showLoginScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showRegisterScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showForgotPasswordScreen() -> Verify { return Verify(method: .m_showForgotPasswordScreen)} - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter) -> Verify { return Verify(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`))} - public static func showWebBrowser(title: Parameter, url: Parameter) -> Verify { return Verify(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`))} - public static func showSSOWebBrowser(title: Parameter) -> Verify { return Verify(method: .m_showSSOWebBrowser__title_title(`title`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`))} - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`))} - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func backToRoot(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_backToRoot__animated_animated(`animated`), performs: perform) - } - public static func back(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_back__animated_animated(`animated`), performs: perform) - } - public static func backWithFade(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_backWithFade, performs: perform) - } - public static func dismiss(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_dismiss__animated_animated(`animated`), performs: perform) - } - public static func removeLastView(controllers: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_removeLastView__controllers_controllers(`controllers`), performs: perform) - } - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter, perform: @escaping (LogistrationSourceScreen, PostLoginData?) -> Void) -> Perform { - return Perform(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`), performs: perform) - } - public static func showStartupScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showStartupScreen, performs: perform) - } - public static func showLoginScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showRegisterScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showForgotPasswordScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showForgotPasswordScreen, performs: perform) - } - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter, perform: @escaping (String?, LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`), performs: perform) - } - public static func showWebBrowser(title: Parameter, url: Parameter, perform: @escaping (String, URL) -> Void) -> Perform { - return Perform(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`), performs: perform) - } - public static func showSSOWebBrowser(title: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showSSOWebBrowser__title_title(`title`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter, perform: @escaping (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>, perform: @escaping (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>, perform: @escaping (UIModalTransitionStyle, any View, (() -> Void)?) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>, perform: @escaping (UIModalTransitionStyle, Bool, () -> any View) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CalendarManagerProtocol -@MainActor -open class CalendarManagerProtocolMock: CalendarManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func createCalendarIfNeeded() { - addInvocation(.m_createCalendarIfNeeded) - let perform = methodPerformValue(.m_createCalendarIfNeeded) as? () -> Void - perform?() - } - - open func filterCoursesBySelected(fetchedCourses: [CourseForSync]) -> [CourseForSync] { - addInvocation(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) - let perform = methodPerformValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) as? ([CourseForSync]) -> Void - perform?(`fetchedCourses`) - var __value: [CourseForSync] - do { - __value = try methodReturnValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))).casted() - } catch { - onFatalFailure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - Failure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - } - return __value - } - - open func removeOldCalendar() { - addInvocation(.m_removeOldCalendar) - let perform = methodPerformValue(.m_removeOldCalendar) as? () -> Void - perform?() - } - - open func removeOutdatedEvents(courseID: String) { - addInvocation(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - } - - open func syncCourse(courseID: String, courseName: String, dates: CourseDates) { - addInvocation(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) - let perform = methodPerformValue(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) as? (String, String, CourseDates) -> Void - perform?(`courseID`, `courseName`, `dates`) - } - - open func requestAccess() -> Bool { - addInvocation(.m_requestAccess) - let perform = methodPerformValue(.m_requestAccess) as? () -> Void - perform?() - var __value: Bool - do { - __value = try methodReturnValue(.m_requestAccess).casted() - } catch { - onFatalFailure("Stub return value not specified for requestAccess(). Use given") - Failure("Stub return value not specified for requestAccess(). Use given") - } - return __value - } - - open func courseStatus(courseID: String) -> SyncStatus { - addInvocation(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: SyncStatus - do { - __value = try methodReturnValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for courseStatus(courseID: String). Use given") - Failure("Stub return value not specified for courseStatus(courseID: String). Use given") - } - return __value - } - - open func clearAllData(removeCalendar: Bool) { - addInvocation(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) - let perform = methodPerformValue(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) as? (Bool) -> Void - perform?(`removeCalendar`) - } - - open func isDatesChanged(courseID: String, checksum: String) -> Bool { - addInvocation(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) - let perform = methodPerformValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) as? (String, String) -> Void - perform?(`courseID`, `checksum`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - Failure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - } - return __value - } - - - fileprivate enum MethodType { - case m_createCalendarIfNeeded - case m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>) - case m_removeOldCalendar - case m_removeOutdatedEvents__courseID_courseID(Parameter) - case m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter, Parameter, Parameter) - case m_requestAccess - case m_courseStatus__courseID_courseID(Parameter) - case m_clearAllData__removeCalendar_removeCalendar(Parameter) - case m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_createCalendarIfNeeded, .m_createCalendarIfNeeded): return .match - - case (.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let lhsFetchedcourses), .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let rhsFetchedcourses)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFetchedcourses, rhs: rhsFetchedcourses, with: matcher), lhsFetchedcourses, rhsFetchedcourses, "fetchedCourses")) - return Matcher.ComparisonResult(results) - - case (.m_removeOldCalendar, .m_removeOldCalendar): return .match - - case (.m_removeOutdatedEvents__courseID_courseID(let lhsCourseid), .m_removeOutdatedEvents__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let lhsCourseid, let lhsCoursename, let lhsDates), .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let rhsCourseid, let rhsCoursename, let rhsDates)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDates, rhs: rhsDates, with: matcher), lhsDates, rhsDates, "dates")) - return Matcher.ComparisonResult(results) - - case (.m_requestAccess, .m_requestAccess): return .match - - case (.m_courseStatus__courseID_courseID(let lhsCourseid), .m_courseStatus__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_clearAllData__removeCalendar_removeCalendar(let lhsRemovecalendar), .m_clearAllData__removeCalendar_removeCalendar(let rhsRemovecalendar)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRemovecalendar, rhs: rhsRemovecalendar, with: matcher), lhsRemovecalendar, rhsRemovecalendar, "removeCalendar")) - return Matcher.ComparisonResult(results) - - case (.m_isDatesChanged__courseID_courseIDchecksum_checksum(let lhsCourseid, let lhsChecksum), .m_isDatesChanged__courseID_courseIDchecksum_checksum(let rhsCourseid, let rhsChecksum)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsChecksum, rhs: rhsChecksum, with: matcher), lhsChecksum, rhsChecksum, "checksum")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_createCalendarIfNeeded: return 0 - case let .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(p0): return p0.intValue - case .m_removeOldCalendar: return 0 - case let .m_removeOutdatedEvents__courseID_courseID(p0): return p0.intValue - case let .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case .m_requestAccess: return 0 - case let .m_courseStatus__courseID_courseID(p0): return p0.intValue - case let .m_clearAllData__removeCalendar_removeCalendar(p0): return p0.intValue - case let .m_isDatesChanged__courseID_courseIDchecksum_checksum(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_createCalendarIfNeeded: return ".createCalendarIfNeeded()" - case .m_filterCoursesBySelected__fetchedCourses_fetchedCourses: return ".filterCoursesBySelected(fetchedCourses:)" - case .m_removeOldCalendar: return ".removeOldCalendar()" - case .m_removeOutdatedEvents__courseID_courseID: return ".removeOutdatedEvents(courseID:)" - case .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates: return ".syncCourse(courseID:courseName:dates:)" - case .m_requestAccess: return ".requestAccess()" - case .m_courseStatus__courseID_courseID: return ".courseStatus(courseID:)" - case .m_clearAllData__removeCalendar_removeCalendar: return ".clearAllData(removeCalendar:)" - case .m_isDatesChanged__courseID_courseIDchecksum_checksum: return ".isDatesChanged(courseID:checksum:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willReturn: [CourseForSync]...) -> MethodStub { - return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func requestAccess(willReturn: Bool...) -> MethodStub { - return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func courseStatus(courseID: Parameter, willReturn: SyncStatus...) -> MethodStub { - return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willProduce: (Stubber<[CourseForSync]>) -> Void) -> MethodStub { - let willReturn: [[CourseForSync]] = [] - let given: Given = { return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([CourseForSync]).self) - willProduce(stubber) - return given - } - public static func requestAccess(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func courseStatus(courseID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [SyncStatus] = [] - let given: Given = { return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (SyncStatus).self) - willProduce(stubber) - return given - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func createCalendarIfNeeded() -> Verify { return Verify(method: .m_createCalendarIfNeeded)} - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>) -> Verify { return Verify(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`))} - public static func removeOldCalendar() -> Verify { return Verify(method: .m_removeOldCalendar)} - public static func removeOutdatedEvents(courseID: Parameter) -> Verify { return Verify(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`))} - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter) -> Verify { return Verify(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`))} - public static func requestAccess() -> Verify { return Verify(method: .m_requestAccess)} - public static func courseStatus(courseID: Parameter) -> Verify { return Verify(method: .m_courseStatus__courseID_courseID(`courseID`))} - public static func clearAllData(removeCalendar: Parameter) -> Verify { return Verify(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`))} - public static func isDatesChanged(courseID: Parameter, checksum: Parameter) -> Verify { return Verify(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func createCalendarIfNeeded(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_createCalendarIfNeeded, performs: perform) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, perform: @escaping ([CourseForSync]) -> Void) -> Perform { - return Perform(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), performs: perform) - } - public static func removeOldCalendar(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeOldCalendar, performs: perform) - } - public static func removeOutdatedEvents(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`), performs: perform) - } - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter, perform: @escaping (String, String, CourseDates) -> Void) -> Perform { - return Perform(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`), performs: perform) - } - public static func requestAccess(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_requestAccess, performs: perform) - } - public static func courseStatus(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_courseStatus__courseID_courseID(`courseID`), performs: perform) - } - public static func clearAllData(removeCalendar: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`), performs: perform) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConfigProtocol - -open class ConfigProtocolMock: ConfigProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var baseURL: URL { - get { invocations.append(.p_baseURL_get); return __p_baseURL ?? givenGetterValue(.p_baseURL_get, "ConfigProtocolMock - stub value for baseURL was not defined") } - } - private var __p_baseURL: (URL)? - - public var baseSSOURL: URL { - get { invocations.append(.p_baseSSOURL_get); return __p_baseSSOURL ?? givenGetterValue(.p_baseSSOURL_get, "ConfigProtocolMock - stub value for baseSSOURL was not defined") } - } - private var __p_baseSSOURL: (URL)? - - public var ssoFinishedURL: URL { - get { invocations.append(.p_ssoFinishedURL_get); return __p_ssoFinishedURL ?? givenGetterValue(.p_ssoFinishedURL_get, "ConfigProtocolMock - stub value for ssoFinishedURL was not defined") } - } - private var __p_ssoFinishedURL: (URL)? - - public var ssoButtonTitle: [String: Any] { - get { invocations.append(.p_ssoButtonTitle_get); return __p_ssoButtonTitle ?? givenGetterValue(.p_ssoButtonTitle_get, "ConfigProtocolMock - stub value for ssoButtonTitle was not defined") } - } - private var __p_ssoButtonTitle: ([String: Any])? - - public var oAuthClientId: String { - get { invocations.append(.p_oAuthClientId_get); return __p_oAuthClientId ?? givenGetterValue(.p_oAuthClientId_get, "ConfigProtocolMock - stub value for oAuthClientId was not defined") } - } - private var __p_oAuthClientId: (String)? - - public var tokenType: TokenType { - get { invocations.append(.p_tokenType_get); return __p_tokenType ?? givenGetterValue(.p_tokenType_get, "ConfigProtocolMock - stub value for tokenType was not defined") } - } - private var __p_tokenType: (TokenType)? - - public var feedbackEmail: String { - get { invocations.append(.p_feedbackEmail_get); return __p_feedbackEmail ?? givenGetterValue(.p_feedbackEmail_get, "ConfigProtocolMock - stub value for feedbackEmail was not defined") } - } - private var __p_feedbackEmail: (String)? - - public var appStoreLink: String { - get { invocations.append(.p_appStoreLink_get); return __p_appStoreLink ?? givenGetterValue(.p_appStoreLink_get, "ConfigProtocolMock - stub value for appStoreLink was not defined") } - } - private var __p_appStoreLink: (String)? - - public var faq: URL? { - get { invocations.append(.p_faq_get); return __p_faq ?? optionalGivenGetterValue(.p_faq_get, "ConfigProtocolMock - stub value for faq was not defined") } - } - private var __p_faq: (URL)? - - public var platformName: String { - get { invocations.append(.p_platformName_get); return __p_platformName ?? givenGetterValue(.p_platformName_get, "ConfigProtocolMock - stub value for platformName was not defined") } - } - private var __p_platformName: (String)? - - public var agreement: AgreementConfig { - get { invocations.append(.p_agreement_get); return __p_agreement ?? givenGetterValue(.p_agreement_get, "ConfigProtocolMock - stub value for agreement was not defined") } - } - private var __p_agreement: (AgreementConfig)? - - public var firebase: FirebaseConfig { - get { invocations.append(.p_firebase_get); return __p_firebase ?? givenGetterValue(.p_firebase_get, "ConfigProtocolMock - stub value for firebase was not defined") } - } - private var __p_firebase: (FirebaseConfig)? - - public var facebook: FacebookConfig { - get { invocations.append(.p_facebook_get); return __p_facebook ?? givenGetterValue(.p_facebook_get, "ConfigProtocolMock - stub value for facebook was not defined") } - } - private var __p_facebook: (FacebookConfig)? - - public var microsoft: MicrosoftConfig { - get { invocations.append(.p_microsoft_get); return __p_microsoft ?? givenGetterValue(.p_microsoft_get, "ConfigProtocolMock - stub value for microsoft was not defined") } - } - private var __p_microsoft: (MicrosoftConfig)? - - public var google: GoogleConfig { - get { invocations.append(.p_google_get); return __p_google ?? givenGetterValue(.p_google_get, "ConfigProtocolMock - stub value for google was not defined") } - } - private var __p_google: (GoogleConfig)? - - public var appleSignIn: AppleSignInConfig { - get { invocations.append(.p_appleSignIn_get); return __p_appleSignIn ?? givenGetterValue(.p_appleSignIn_get, "ConfigProtocolMock - stub value for appleSignIn was not defined") } - } - private var __p_appleSignIn: (AppleSignInConfig)? - - public var features: FeaturesConfig { - get { invocations.append(.p_features_get); return __p_features ?? givenGetterValue(.p_features_get, "ConfigProtocolMock - stub value for features was not defined") } - } - private var __p_features: (FeaturesConfig)? - - public var theme: ThemeConfig { - get { invocations.append(.p_theme_get); return __p_theme ?? givenGetterValue(.p_theme_get, "ConfigProtocolMock - stub value for theme was not defined") } - } - private var __p_theme: (ThemeConfig)? - - public var uiComponents: UIComponentsConfig { - get { invocations.append(.p_uiComponents_get); return __p_uiComponents ?? givenGetterValue(.p_uiComponents_get, "ConfigProtocolMock - stub value for uiComponents was not defined") } - } - private var __p_uiComponents: (UIComponentsConfig)? - - public var discovery: DiscoveryConfig { - get { invocations.append(.p_discovery_get); return __p_discovery ?? givenGetterValue(.p_discovery_get, "ConfigProtocolMock - stub value for discovery was not defined") } - } - private var __p_discovery: (DiscoveryConfig)? - - public var dashboard: DashboardConfig { - get { invocations.append(.p_dashboard_get); return __p_dashboard ?? givenGetterValue(.p_dashboard_get, "ConfigProtocolMock - stub value for dashboard was not defined") } - } - private var __p_dashboard: (DashboardConfig)? - - public var braze: BrazeConfig { - get { invocations.append(.p_braze_get); return __p_braze ?? givenGetterValue(.p_braze_get, "ConfigProtocolMock - stub value for braze was not defined") } - } - private var __p_braze: (BrazeConfig)? - - public var branch: BranchConfig { - get { invocations.append(.p_branch_get); return __p_branch ?? givenGetterValue(.p_branch_get, "ConfigProtocolMock - stub value for branch was not defined") } - } - private var __p_branch: (BranchConfig)? - - public var program: DiscoveryConfig { - get { invocations.append(.p_program_get); return __p_program ?? givenGetterValue(.p_program_get, "ConfigProtocolMock - stub value for program was not defined") } - } - private var __p_program: (DiscoveryConfig)? - - public var experimentalFeatures: ExperimentalFeaturesConfig { - get { invocations.append(.p_experimentalFeatures_get); return __p_experimentalFeatures ?? givenGetterValue(.p_experimentalFeatures_get, "ConfigProtocolMock - stub value for experimentalFeatures was not defined") } - } - private var __p_experimentalFeatures: (ExperimentalFeaturesConfig)? - - public var URIScheme: String { - get { invocations.append(.p_URIScheme_get); return __p_URIScheme ?? givenGetterValue(.p_URIScheme_get, "ConfigProtocolMock - stub value for URIScheme was not defined") } - } - private var __p_URIScheme: (String)? - - - - - - - fileprivate enum MethodType { - case p_baseURL_get - case p_baseSSOURL_get - case p_ssoFinishedURL_get - case p_ssoButtonTitle_get - case p_oAuthClientId_get - case p_tokenType_get - case p_feedbackEmail_get - case p_appStoreLink_get - case p_faq_get - case p_platformName_get - case p_agreement_get - case p_firebase_get - case p_facebook_get - case p_microsoft_get - case p_google_get - case p_appleSignIn_get - case p_features_get - case p_theme_get - case p_uiComponents_get - case p_discovery_get - case p_dashboard_get - case p_braze_get - case p_branch_get - case p_program_get - case p_experimentalFeatures_get - case p_URIScheme_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_baseURL_get,.p_baseURL_get): return Matcher.ComparisonResult.match - case (.p_baseSSOURL_get,.p_baseSSOURL_get): return Matcher.ComparisonResult.match - case (.p_ssoFinishedURL_get,.p_ssoFinishedURL_get): return Matcher.ComparisonResult.match - case (.p_ssoButtonTitle_get,.p_ssoButtonTitle_get): return Matcher.ComparisonResult.match - case (.p_oAuthClientId_get,.p_oAuthClientId_get): return Matcher.ComparisonResult.match - case (.p_tokenType_get,.p_tokenType_get): return Matcher.ComparisonResult.match - case (.p_feedbackEmail_get,.p_feedbackEmail_get): return Matcher.ComparisonResult.match - case (.p_appStoreLink_get,.p_appStoreLink_get): return Matcher.ComparisonResult.match - case (.p_faq_get,.p_faq_get): return Matcher.ComparisonResult.match - case (.p_platformName_get,.p_platformName_get): return Matcher.ComparisonResult.match - case (.p_agreement_get,.p_agreement_get): return Matcher.ComparisonResult.match - case (.p_firebase_get,.p_firebase_get): return Matcher.ComparisonResult.match - case (.p_facebook_get,.p_facebook_get): return Matcher.ComparisonResult.match - case (.p_microsoft_get,.p_microsoft_get): return Matcher.ComparisonResult.match - case (.p_google_get,.p_google_get): return Matcher.ComparisonResult.match - case (.p_appleSignIn_get,.p_appleSignIn_get): return Matcher.ComparisonResult.match - case (.p_features_get,.p_features_get): return Matcher.ComparisonResult.match - case (.p_theme_get,.p_theme_get): return Matcher.ComparisonResult.match - case (.p_uiComponents_get,.p_uiComponents_get): return Matcher.ComparisonResult.match - case (.p_discovery_get,.p_discovery_get): return Matcher.ComparisonResult.match - case (.p_dashboard_get,.p_dashboard_get): return Matcher.ComparisonResult.match - case (.p_braze_get,.p_braze_get): return Matcher.ComparisonResult.match - case (.p_branch_get,.p_branch_get): return Matcher.ComparisonResult.match - case (.p_program_get,.p_program_get): return Matcher.ComparisonResult.match - case (.p_experimentalFeatures_get,.p_experimentalFeatures_get): return Matcher.ComparisonResult.match - case (.p_URIScheme_get,.p_URIScheme_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_baseURL_get: return 0 - case .p_baseSSOURL_get: return 0 - case .p_ssoFinishedURL_get: return 0 - case .p_ssoButtonTitle_get: return 0 - case .p_oAuthClientId_get: return 0 - case .p_tokenType_get: return 0 - case .p_feedbackEmail_get: return 0 - case .p_appStoreLink_get: return 0 - case .p_faq_get: return 0 - case .p_platformName_get: return 0 - case .p_agreement_get: return 0 - case .p_firebase_get: return 0 - case .p_facebook_get: return 0 - case .p_microsoft_get: return 0 - case .p_google_get: return 0 - case .p_appleSignIn_get: return 0 - case .p_features_get: return 0 - case .p_theme_get: return 0 - case .p_uiComponents_get: return 0 - case .p_discovery_get: return 0 - case .p_dashboard_get: return 0 - case .p_braze_get: return 0 - case .p_branch_get: return 0 - case .p_program_get: return 0 - case .p_experimentalFeatures_get: return 0 - case .p_URIScheme_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_baseURL_get: return "[get] .baseURL" - case .p_baseSSOURL_get: return "[get] .baseSSOURL" - case .p_ssoFinishedURL_get: return "[get] .ssoFinishedURL" - case .p_ssoButtonTitle_get: return "[get] .ssoButtonTitle" - case .p_oAuthClientId_get: return "[get] .oAuthClientId" - case .p_tokenType_get: return "[get] .tokenType" - case .p_feedbackEmail_get: return "[get] .feedbackEmail" - case .p_appStoreLink_get: return "[get] .appStoreLink" - case .p_faq_get: return "[get] .faq" - case .p_platformName_get: return "[get] .platformName" - case .p_agreement_get: return "[get] .agreement" - case .p_firebase_get: return "[get] .firebase" - case .p_facebook_get: return "[get] .facebook" - case .p_microsoft_get: return "[get] .microsoft" - case .p_google_get: return "[get] .google" - case .p_appleSignIn_get: return "[get] .appleSignIn" - case .p_features_get: return "[get] .features" - case .p_theme_get: return "[get] .theme" - case .p_uiComponents_get: return "[get] .uiComponents" - case .p_discovery_get: return "[get] .discovery" - case .p_dashboard_get: return "[get] .dashboard" - case .p_braze_get: return "[get] .braze" - case .p_branch_get: return "[get] .branch" - case .p_program_get: return "[get] .program" - case .p_experimentalFeatures_get: return "[get] .experimentalFeatures" - case .p_URIScheme_get: return "[get] .URIScheme" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func baseURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func baseSSOURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseSSOURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoFinishedURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_ssoFinishedURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoButtonTitle(getter defaultValue: [String: Any]...) -> PropertyStub { - return Given(method: .p_ssoButtonTitle_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func oAuthClientId(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_oAuthClientId_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func tokenType(getter defaultValue: TokenType...) -> PropertyStub { - return Given(method: .p_tokenType_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func feedbackEmail(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_feedbackEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appStoreLink(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_appStoreLink_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func faq(getter defaultValue: URL?...) -> PropertyStub { - return Given(method: .p_faq_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func platformName(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_platformName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func agreement(getter defaultValue: AgreementConfig...) -> PropertyStub { - return Given(method: .p_agreement_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func firebase(getter defaultValue: FirebaseConfig...) -> PropertyStub { - return Given(method: .p_firebase_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func facebook(getter defaultValue: FacebookConfig...) -> PropertyStub { - return Given(method: .p_facebook_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func microsoft(getter defaultValue: MicrosoftConfig...) -> PropertyStub { - return Given(method: .p_microsoft_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func google(getter defaultValue: GoogleConfig...) -> PropertyStub { - return Given(method: .p_google_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignIn(getter defaultValue: AppleSignInConfig...) -> PropertyStub { - return Given(method: .p_appleSignIn_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func features(getter defaultValue: FeaturesConfig...) -> PropertyStub { - return Given(method: .p_features_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func theme(getter defaultValue: ThemeConfig...) -> PropertyStub { - return Given(method: .p_theme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func uiComponents(getter defaultValue: UIComponentsConfig...) -> PropertyStub { - return Given(method: .p_uiComponents_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func discovery(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_discovery_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func dashboard(getter defaultValue: DashboardConfig...) -> PropertyStub { - return Given(method: .p_dashboard_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func braze(getter defaultValue: BrazeConfig...) -> PropertyStub { - return Given(method: .p_braze_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func branch(getter defaultValue: BranchConfig...) -> PropertyStub { - return Given(method: .p_branch_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func program(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_program_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func experimentalFeatures(getter defaultValue: ExperimentalFeaturesConfig...) -> PropertyStub { - return Given(method: .p_experimentalFeatures_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func URIScheme(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_URIScheme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var baseURL: Verify { return Verify(method: .p_baseURL_get) } - public static var baseSSOURL: Verify { return Verify(method: .p_baseSSOURL_get) } - public static var ssoFinishedURL: Verify { return Verify(method: .p_ssoFinishedURL_get) } - public static var ssoButtonTitle: Verify { return Verify(method: .p_ssoButtonTitle_get) } - public static var oAuthClientId: Verify { return Verify(method: .p_oAuthClientId_get) } - public static var tokenType: Verify { return Verify(method: .p_tokenType_get) } - public static var feedbackEmail: Verify { return Verify(method: .p_feedbackEmail_get) } - public static var appStoreLink: Verify { return Verify(method: .p_appStoreLink_get) } - public static var faq: Verify { return Verify(method: .p_faq_get) } - public static var platformName: Verify { return Verify(method: .p_platformName_get) } - public static var agreement: Verify { return Verify(method: .p_agreement_get) } - public static var firebase: Verify { return Verify(method: .p_firebase_get) } - public static var facebook: Verify { return Verify(method: .p_facebook_get) } - public static var microsoft: Verify { return Verify(method: .p_microsoft_get) } - public static var google: Verify { return Verify(method: .p_google_get) } - public static var appleSignIn: Verify { return Verify(method: .p_appleSignIn_get) } - public static var features: Verify { return Verify(method: .p_features_get) } - public static var theme: Verify { return Verify(method: .p_theme_get) } - public static var uiComponents: Verify { return Verify(method: .p_uiComponents_get) } - public static var discovery: Verify { return Verify(method: .p_discovery_get) } - public static var dashboard: Verify { return Verify(method: .p_dashboard_get) } - public static var braze: Verify { return Verify(method: .p_braze_get) } - public static var branch: Verify { return Verify(method: .p_branch_get) } - public static var program: Verify { return Verify(method: .p_program_get) } - public static var experimentalFeatures: Verify { return Verify(method: .p_experimentalFeatures_get) } - public static var URIScheme: Verify { return Verify(method: .p_URIScheme_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConnectivityProtocol -@MainActor -open class ConnectivityProtocolMock: ConnectivityProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var isInternetAvaliable: Bool { - get { invocations.append(.p_isInternetAvaliable_get); return __p_isInternetAvaliable ?? givenGetterValue(.p_isInternetAvaliable_get, "ConnectivityProtocolMock - stub value for isInternetAvaliable was not defined") } - } - private var __p_isInternetAvaliable: (Bool)? - - public var isMobileData: Bool { - get { invocations.append(.p_isMobileData_get); return __p_isMobileData ?? givenGetterValue(.p_isMobileData_get, "ConnectivityProtocolMock - stub value for isMobileData was not defined") } - } - private var __p_isMobileData: (Bool)? - - public var internetReachableSubject: CurrentValueSubject { - get { invocations.append(.p_internetReachableSubject_get); return __p_internetReachableSubject ?? givenGetterValue(.p_internetReachableSubject_get, "ConnectivityProtocolMock - stub value for internetReachableSubject was not defined") } - } - private var __p_internetReachableSubject: (CurrentValueSubject)? - - - - - - - fileprivate enum MethodType { - case p_isInternetAvaliable_get - case p_isMobileData_get - case p_internetReachableSubject_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_isInternetAvaliable_get,.p_isInternetAvaliable_get): return Matcher.ComparisonResult.match - case (.p_isMobileData_get,.p_isMobileData_get): return Matcher.ComparisonResult.match - case (.p_internetReachableSubject_get,.p_internetReachableSubject_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_isInternetAvaliable_get: return 0 - case .p_isMobileData_get: return 0 - case .p_internetReachableSubject_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_isInternetAvaliable_get: return "[get] .isInternetAvaliable" - case .p_isMobileData_get: return "[get] .isMobileData" - case .p_internetReachableSubject_get: return "[get] .internetReachableSubject" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func isInternetAvaliable(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isInternetAvaliable_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func isMobileData(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isMobileData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func internetReachableSubject(getter defaultValue: CurrentValueSubject...) -> PropertyStub { - return Given(method: .p_internetReachableSubject_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var isInternetAvaliable: Verify { return Verify(method: .p_isInternetAvaliable_get) } - public static var isMobileData: Verify { return Verify(method: .p_isMobileData_get) } - public static var internetReachableSubject: Verify { return Verify(method: .p_internetReachableSubject_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreAnalytics - -open class CoreAnalyticsMock: CoreAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { - addInvocation(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) - let perform = methodPerformValue(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) as? (AnalyticsEvent, EventBIValue, String?, Int?) -> Void - perform?(`event`, `biValue`, `action`, `rating`) - } - - open func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { - addInvocation(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) - let perform = methodPerformValue(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) as? (AnalyticsEvent, EventBIValue, String, String) -> Void - perform?(`event`, `bivalue`, `value`, `oldValue`) - } - - open func trackEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackScreenEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackScreenEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - - fileprivate enum MethodType { - case m_trackEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter, Parameter, Parameter, Parameter) - case m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter, Parameter, Parameter, Parameter) - case m_trackEvent__event(Parameter) - case m_trackEvent__eventbiValue_biValue(Parameter, Parameter) - case m_trackScreenEvent__event(Parameter) - case m_trackScreenEvent__eventbiValue_biValue(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_trackEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackScreenEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_appreview__eventbiValue_biValueaction_actionrating_rating(let lhsEvent, let lhsBivalue, let lhsAction, let lhsRating), .m_appreview__eventbiValue_biValueaction_actionrating_rating(let rhsEvent, let rhsBivalue, let rhsAction, let rhsRating)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRating, rhs: rhsRating, with: matcher), lhsRating, rhsRating, "rating")) - return Matcher.ComparisonResult(results) - - case (.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let lhsEvent, let lhsBivalue, let lhsValue, let lhsOldvalue), .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let rhsEvent, let rhsBivalue, let rhsValue, let rhsOldvalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "bivalue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsValue, rhs: rhsValue, with: matcher), lhsValue, rhsValue, "value")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOldvalue, rhs: rhsOldvalue, with: matcher), lhsOldvalue, rhsOldvalue, "oldValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__event(let lhsEvent), .m_trackEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__event(let lhsEvent), .m_trackScreenEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackScreenEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_trackEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_trackScreenEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_appreview__eventbiValue_biValueaction_actionrating_rating(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_trackEvent__event(p0): return p0.intValue - case let .m_trackEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__event(p0): return p0.intValue - case let .m_trackScreenEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_trackEvent__eventparameters_parameters: return ".trackEvent(_:parameters:)" - case .m_trackEvent__eventbiValue_biValueparameters_parameters: return ".trackEvent(_:biValue:parameters:)" - case .m_trackScreenEvent__eventparameters_parameters: return ".trackScreenEvent(_:parameters:)" - case .m_trackScreenEvent__eventbiValue_biValueparameters_parameters: return ".trackScreenEvent(_:biValue:parameters:)" - case .m_appreview__eventbiValue_biValueaction_actionrating_rating: return ".appreview(_:biValue:action:rating:)" - case .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue: return ".videoQualityChanged(_:bivalue:value:oldValue:)" - case .m_trackEvent__event: return ".trackEvent(_:)" - case .m_trackEvent__eventbiValue_biValue: return ".trackEvent(_:biValue:)" - case .m_trackScreenEvent__event: return ".trackScreenEvent(_:)" - case .m_trackScreenEvent__eventbiValue_biValue: return ".trackScreenEvent(_:biValue:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter) -> Verify { return Verify(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`))} - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter) -> Verify { return Verify(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`))} - public static func trackEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackEvent__event(`event`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`))} - public static func trackScreenEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__event(`event`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String?, Int?) -> Void) -> Perform { - return Perform(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`), performs: perform) - } - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String, String) -> Void) -> Perform { - return Perform(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`), performs: perform) - } - public static func trackEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackEvent__event(`event`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__event(`event`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CorePersistenceProtocol - -open class CorePersistenceProtocolMock: CorePersistenceProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func set(userId: Int) { - addInvocation(.m_set__userId_userId(Parameter.value(`userId`))) - let perform = methodPerformValue(.m_set__userId_userId(Parameter.value(`userId`))) as? (Int) -> Void - perform?(`userId`) - } - - open func getUserID() -> Int? { - addInvocation(.m_getUserID) - let perform = methodPerformValue(.m_getUserID) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getUserID).casted() - } catch { - // do nothing - } - return __value - } - - @MainActor - open func publisher() throws -> AnyPublisher { - addInvocation(.m_publisher) - let perform = methodPerformValue(.m_publisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_publisher).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for publisher(). Use given") - Failure("Stub return value not specified for publisher(). Use given") - } catch { - throw error - } - return __value - } - - open func addToDownloadQueue(tasks: [DownloadDataTask]) { - addInvocation(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) as? ([DownloadDataTask]) -> Void - perform?(`tasks`) - } - - open func saveOfflineProgress(progress: OfflineProgress) { - addInvocation(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) - let perform = methodPerformValue(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) as? (OfflineProgress) -> Void - perform?(`progress`) - } - - open func loadProgress(for blockID: String) -> OfflineProgress? { - addInvocation(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - var __value: OfflineProgress? = nil - do { - __value = try methodReturnValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))).casted() - } catch { - // do nothing - } - return __value - } - - open func loadAllOfflineProgress() -> [OfflineProgress] { - addInvocation(.m_loadAllOfflineProgress) - let perform = methodPerformValue(.m_loadAllOfflineProgress) as? () -> Void - perform?() - var __value: [OfflineProgress] - do { - __value = try methodReturnValue(.m_loadAllOfflineProgress).casted() - } catch { - onFatalFailure("Stub return value not specified for loadAllOfflineProgress(). Use given") - Failure("Stub return value not specified for loadAllOfflineProgress(). Use given") - } - return __value - } - - open func deleteProgress(for blockID: String) { - addInvocation(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - } - - open func deleteAllProgress() { - addInvocation(.m_deleteAllProgress) - let perform = methodPerformValue(.m_deleteAllProgress) as? () -> Void - perform?() - } - - open func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { - addInvocation(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) as? ([CourseBlock], DownloadQuality) -> Void - perform?(`blocks`, `downloadQuality`) - } - - open func updateTask(task: DownloadDataTask) { - addInvocation(.m_updateTask__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_updateTask__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - } - - open func downloadDataTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getDownloadDataTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasks) - let perform = methodPerformValue(.m_getDownloadDataTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasks(). Use given") - Failure("Stub return value not specified for getDownloadDataTasks(). Use given") - } - return __value - } - - open func getDownloadDataTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func deleteDownloadDataTasks(ids: [String]) { - addInvocation(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) - let perform = methodPerformValue(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) as? ([String]) -> Void - perform?(`ids`) - } - - - fileprivate enum MethodType { - case m_set__userId_userId(Parameter) - case m_getUserID - case m_publisher - case m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>) - case m_saveOfflineProgress__progress_progress(Parameter) - case m_loadProgress__for_blockID(Parameter) - case m_loadAllOfflineProgress - case m_deleteProgress__for_blockID(Parameter) - case m_deleteAllProgress - case m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>, Parameter) - case m_updateTask__task_task(Parameter) - case m_downloadDataTask__for_blockId(Parameter) - case m_getDownloadDataTasks - case m_getDownloadDataTasksForCourse__courseId(Parameter) - case m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_set__userId_userId(let lhsUserid), .m_set__userId_userId(let rhsUserid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUserid, rhs: rhsUserid, with: matcher), lhsUserid, rhsUserid, "userId")) - return Matcher.ComparisonResult(results) - - case (.m_getUserID, .m_getUserID): return .match - - case (.m_publisher, .m_publisher): return .match - - case (.m_addToDownloadQueue__tasks_tasks(let lhsTasks), .m_addToDownloadQueue__tasks_tasks(let rhsTasks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTasks, rhs: rhsTasks, with: matcher), lhsTasks, rhsTasks, "tasks")) - return Matcher.ComparisonResult(results) - - case (.m_saveOfflineProgress__progress_progress(let lhsProgress), .m_saveOfflineProgress__progress_progress(let rhsProgress)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsProgress, rhs: rhsProgress, with: matcher), lhsProgress, rhsProgress, "progress")) - return Matcher.ComparisonResult(results) - - case (.m_loadProgress__for_blockID(let lhsBlockid), .m_loadProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_loadAllOfflineProgress, .m_loadAllOfflineProgress): return .match - - case (.m_deleteProgress__for_blockID(let lhsBlockid), .m_deleteProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_deleteAllProgress, .m_deleteAllProgress): return .match - - case (.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let lhsBlocks, let lhsDownloadquality), .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let rhsBlocks, let rhsDownloadquality)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadquality, rhs: rhsDownloadquality, with: matcher), lhsDownloadquality, rhsDownloadquality, "downloadQuality")) - return Matcher.ComparisonResult(results) - - case (.m_updateTask__task_task(let lhsTask), .m_updateTask__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_downloadDataTask__for_blockId(let lhsBlockid), .m_downloadDataTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadDataTasks, .m_getDownloadDataTasks): return .match - - case (.m_getDownloadDataTasksForCourse__courseId(let lhsCourseid), .m_getDownloadDataTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_deleteDownloadDataTasks__ids_ids(let lhsIds), .m_deleteDownloadDataTasks__ids_ids(let rhsIds)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIds, rhs: rhsIds, with: matcher), lhsIds, rhsIds, "ids")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_set__userId_userId(p0): return p0.intValue - case .m_getUserID: return 0 - case .m_publisher: return 0 - case let .m_addToDownloadQueue__tasks_tasks(p0): return p0.intValue - case let .m_saveOfflineProgress__progress_progress(p0): return p0.intValue - case let .m_loadProgress__for_blockID(p0): return p0.intValue - case .m_loadAllOfflineProgress: return 0 - case let .m_deleteProgress__for_blockID(p0): return p0.intValue - case .m_deleteAllProgress: return 0 - case let .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(p0, p1): return p0.intValue + p1.intValue - case let .m_updateTask__task_task(p0): return p0.intValue - case let .m_downloadDataTask__for_blockId(p0): return p0.intValue - case .m_getDownloadDataTasks: return 0 - case let .m_getDownloadDataTasksForCourse__courseId(p0): return p0.intValue - case let .m_deleteDownloadDataTasks__ids_ids(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_set__userId_userId: return ".set(userId:)" - case .m_getUserID: return ".getUserID()" - case .m_publisher: return ".publisher()" - case .m_addToDownloadQueue__tasks_tasks: return ".addToDownloadQueue(tasks:)" - case .m_saveOfflineProgress__progress_progress: return ".saveOfflineProgress(progress:)" - case .m_loadProgress__for_blockID: return ".loadProgress(for:)" - case .m_loadAllOfflineProgress: return ".loadAllOfflineProgress()" - case .m_deleteProgress__for_blockID: return ".deleteProgress(for:)" - case .m_deleteAllProgress: return ".deleteAllProgress()" - case .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality: return ".addToDownloadQueue(blocks:downloadQuality:)" - case .m_updateTask__task_task: return ".updateTask(task:)" - case .m_downloadDataTask__for_blockId: return ".downloadDataTask(for:)" - case .m_getDownloadDataTasks: return ".getDownloadDataTasks()" - case .m_getDownloadDataTasksForCourse__courseId: return ".getDownloadDataTasksForCourse(_:)" - case .m_deleteDownloadDataTasks__ids_ids: return ".deleteDownloadDataTasks(ids:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getUserID(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @MainActor - public static func publisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_publisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadProgress(for blockID: Parameter, willReturn: OfflineProgress?...) -> MethodStub { - return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadAllOfflineProgress(willReturn: [OfflineProgress]...) -> MethodStub { - return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadDataTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getUserID(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func loadProgress(for blockID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [OfflineProgress?] = [] - let given: Given = { return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (OfflineProgress?).self) - willProduce(stubber) - return given - } - public static func loadAllOfflineProgress(willProduce: (Stubber<[OfflineProgress]>) -> Void) -> MethodStub { - let willReturn: [[OfflineProgress]] = [] - let given: Given = { return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([OfflineProgress]).self) - willProduce(stubber) - return given - } - public static func downloadDataTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - @MainActor - public static func publisher(willThrow: Error...) -> MethodStub { - return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) - } - @MainActor - public static func publisher(willProduce: (StubberThrows>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func set(userId: Parameter) -> Verify { return Verify(method: .m_set__userId_userId(`userId`))} - public static func getUserID() -> Verify { return Verify(method: .m_getUserID)} - @MainActor - public static func publisher() -> Verify { return Verify(method: .m_publisher)} - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>) -> Verify { return Verify(method: .m_addToDownloadQueue__tasks_tasks(`tasks`))} - public static func saveOfflineProgress(progress: Parameter) -> Verify { return Verify(method: .m_saveOfflineProgress__progress_progress(`progress`))} - public static func loadProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_loadProgress__for_blockID(`blockID`))} - public static func loadAllOfflineProgress() -> Verify { return Verify(method: .m_loadAllOfflineProgress)} - public static func deleteProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_deleteProgress__for_blockID(`blockID`))} - public static func deleteAllProgress() -> Verify { return Verify(method: .m_deleteAllProgress)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`))} - public static func updateTask(task: Parameter) -> Verify { return Verify(method: .m_updateTask__task_task(`task`))} - public static func downloadDataTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadDataTask__for_blockId(`blockId`))} - public static func getDownloadDataTasks() -> Verify { return Verify(method: .m_getDownloadDataTasks)} - public static func getDownloadDataTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`))} - public static func deleteDownloadDataTasks(ids: Parameter<[String]>) -> Verify { return Verify(method: .m_deleteDownloadDataTasks__ids_ids(`ids`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func set(userId: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_set__userId_userId(`userId`), performs: perform) - } - public static func getUserID(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getUserID, performs: perform) - } - @MainActor - public static func publisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_publisher, performs: perform) - } - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>, perform: @escaping ([DownloadDataTask]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__tasks_tasks(`tasks`), performs: perform) - } - public static func saveOfflineProgress(progress: Parameter, perform: @escaping (OfflineProgress) -> Void) -> Perform { - return Perform(method: .m_saveOfflineProgress__progress_progress(`progress`), performs: perform) - } - public static func loadProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_loadProgress__for_blockID(`blockID`), performs: perform) - } - public static func loadAllOfflineProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_loadAllOfflineProgress, performs: perform) - } - public static func deleteProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_deleteProgress__for_blockID(`blockID`), performs: perform) - } - public static func deleteAllProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAllProgress, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter, perform: @escaping ([CourseBlock], DownloadQuality) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`), performs: perform) - } - public static func updateTask(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_updateTask__task_task(`task`), performs: perform) - } - public static func downloadDataTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadDataTask__for_blockId(`blockId`), performs: perform) - } - public static func getDownloadDataTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasks, performs: perform) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func deleteDownloadDataTasks(ids: Parameter<[String]>, perform: @escaping ([String]) -> Void) -> Perform { - return Perform(method: .m_deleteDownloadDataTasks__ids_ids(`ids`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreStorage - -open class CoreStorageMock: CoreStorage, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var accessToken: String? { - get { invocations.append(.p_accessToken_get); return __p_accessToken ?? optionalGivenGetterValue(.p_accessToken_get, "CoreStorageMock - stub value for accessToken was not defined") } - set { invocations.append(.p_accessToken_set(.value(newValue))); __p_accessToken = newValue } - } - private var __p_accessToken: (String)? - - public var refreshToken: String? { - get { invocations.append(.p_refreshToken_get); return __p_refreshToken ?? optionalGivenGetterValue(.p_refreshToken_get, "CoreStorageMock - stub value for refreshToken was not defined") } - set { invocations.append(.p_refreshToken_set(.value(newValue))); __p_refreshToken = newValue } - } - private var __p_refreshToken: (String)? - - public var pushToken: String? { - get { invocations.append(.p_pushToken_get); return __p_pushToken ?? optionalGivenGetterValue(.p_pushToken_get, "CoreStorageMock - stub value for pushToken was not defined") } - set { invocations.append(.p_pushToken_set(.value(newValue))); __p_pushToken = newValue } - } - private var __p_pushToken: (String)? - - public var appleSignFullName: String? { - get { invocations.append(.p_appleSignFullName_get); return __p_appleSignFullName ?? optionalGivenGetterValue(.p_appleSignFullName_get, "CoreStorageMock - stub value for appleSignFullName was not defined") } - set { invocations.append(.p_appleSignFullName_set(.value(newValue))); __p_appleSignFullName = newValue } - } - private var __p_appleSignFullName: (String)? - - public var appleSignEmail: String? { - get { invocations.append(.p_appleSignEmail_get); return __p_appleSignEmail ?? optionalGivenGetterValue(.p_appleSignEmail_get, "CoreStorageMock - stub value for appleSignEmail was not defined") } - set { invocations.append(.p_appleSignEmail_set(.value(newValue))); __p_appleSignEmail = newValue } - } - private var __p_appleSignEmail: (String)? - - public var cookiesDate: Date? { - get { invocations.append(.p_cookiesDate_get); return __p_cookiesDate ?? optionalGivenGetterValue(.p_cookiesDate_get, "CoreStorageMock - stub value for cookiesDate was not defined") } - set { invocations.append(.p_cookiesDate_set(.value(newValue))); __p_cookiesDate = newValue } - } - private var __p_cookiesDate: (Date)? - - public var reviewLastShownVersion: String? { - get { invocations.append(.p_reviewLastShownVersion_get); return __p_reviewLastShownVersion ?? optionalGivenGetterValue(.p_reviewLastShownVersion_get, "CoreStorageMock - stub value for reviewLastShownVersion was not defined") } - set { invocations.append(.p_reviewLastShownVersion_set(.value(newValue))); __p_reviewLastShownVersion = newValue } - } - private var __p_reviewLastShownVersion: (String)? - - public var lastReviewDate: Date? { - get { invocations.append(.p_lastReviewDate_get); return __p_lastReviewDate ?? optionalGivenGetterValue(.p_lastReviewDate_get, "CoreStorageMock - stub value for lastReviewDate was not defined") } - set { invocations.append(.p_lastReviewDate_set(.value(newValue))); __p_lastReviewDate = newValue } - } - private var __p_lastReviewDate: (Date)? - - public var user: DataLayer.User? { - get { invocations.append(.p_user_get); return __p_user ?? optionalGivenGetterValue(.p_user_get, "CoreStorageMock - stub value for user was not defined") } - set { invocations.append(.p_user_set(.value(newValue))); __p_user = newValue } - } - private var __p_user: (DataLayer.User)? - - public var userSettings: UserSettings? { - get { invocations.append(.p_userSettings_get); return __p_userSettings ?? optionalGivenGetterValue(.p_userSettings_get, "CoreStorageMock - stub value for userSettings was not defined") } - set { invocations.append(.p_userSettings_set(.value(newValue))); __p_userSettings = newValue } - } - private var __p_userSettings: (UserSettings)? - - public var resetAppSupportDirectoryUserData: Bool? { - get { invocations.append(.p_resetAppSupportDirectoryUserData_get); return __p_resetAppSupportDirectoryUserData ?? optionalGivenGetterValue(.p_resetAppSupportDirectoryUserData_get, "CoreStorageMock - stub value for resetAppSupportDirectoryUserData was not defined") } - set { invocations.append(.p_resetAppSupportDirectoryUserData_set(.value(newValue))); __p_resetAppSupportDirectoryUserData = newValue } - } - private var __p_resetAppSupportDirectoryUserData: (Bool)? - - public var useRelativeDates: Bool { - get { invocations.append(.p_useRelativeDates_get); return __p_useRelativeDates ?? givenGetterValue(.p_useRelativeDates_get, "CoreStorageMock - stub value for useRelativeDates was not defined") } - set { invocations.append(.p_useRelativeDates_set(.value(newValue))); __p_useRelativeDates = newValue } - } - private var __p_useRelativeDates: (Bool)? - - public var lastUsedSocialAuth: String? { - get { invocations.append(.p_lastUsedSocialAuth_get); return __p_lastUsedSocialAuth ?? optionalGivenGetterValue(.p_lastUsedSocialAuth_get, "CoreStorageMock - stub value for lastUsedSocialAuth was not defined") } - set { invocations.append(.p_lastUsedSocialAuth_set(.value(newValue))); __p_lastUsedSocialAuth = newValue } - } - private var __p_lastUsedSocialAuth: (String)? - - public var latestAvailableAppVersion: String? { - get { invocations.append(.p_latestAvailableAppVersion_get); return __p_latestAvailableAppVersion ?? optionalGivenGetterValue(.p_latestAvailableAppVersion_get, "CoreStorageMock - stub value for latestAvailableAppVersion was not defined") } - set { invocations.append(.p_latestAvailableAppVersion_set(.value(newValue))); __p_latestAvailableAppVersion = newValue } - } - private var __p_latestAvailableAppVersion: (String)? - - public var updateAppRequired: Bool { - get { invocations.append(.p_updateAppRequired_get); return __p_updateAppRequired ?? givenGetterValue(.p_updateAppRequired_get, "CoreStorageMock - stub value for updateAppRequired was not defined") } - set { invocations.append(.p_updateAppRequired_set(.value(newValue))); __p_updateAppRequired = newValue } - } - private var __p_updateAppRequired: (Bool)? - - - - - - open func clear() { - addInvocation(.m_clear) - let perform = methodPerformValue(.m_clear) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_clear - case p_accessToken_get - case p_accessToken_set(Parameter) - case p_refreshToken_get - case p_refreshToken_set(Parameter) - case p_pushToken_get - case p_pushToken_set(Parameter) - case p_appleSignFullName_get - case p_appleSignFullName_set(Parameter) - case p_appleSignEmail_get - case p_appleSignEmail_set(Parameter) - case p_cookiesDate_get - case p_cookiesDate_set(Parameter) - case p_reviewLastShownVersion_get - case p_reviewLastShownVersion_set(Parameter) - case p_lastReviewDate_get - case p_lastReviewDate_set(Parameter) - case p_user_get - case p_user_set(Parameter) - case p_userSettings_get - case p_userSettings_set(Parameter) - case p_resetAppSupportDirectoryUserData_get - case p_resetAppSupportDirectoryUserData_set(Parameter) - case p_useRelativeDates_get - case p_useRelativeDates_set(Parameter) - case p_lastUsedSocialAuth_get - case p_lastUsedSocialAuth_set(Parameter) - case p_latestAvailableAppVersion_get - case p_latestAvailableAppVersion_set(Parameter) - case p_updateAppRequired_get - case p_updateAppRequired_set(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_clear, .m_clear): return .match - case (.p_accessToken_get,.p_accessToken_get): return Matcher.ComparisonResult.match - case (.p_accessToken_set(let left),.p_accessToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_refreshToken_get,.p_refreshToken_get): return Matcher.ComparisonResult.match - case (.p_refreshToken_set(let left),.p_refreshToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_pushToken_get,.p_pushToken_get): return Matcher.ComparisonResult.match - case (.p_pushToken_set(let left),.p_pushToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignFullName_get,.p_appleSignFullName_get): return Matcher.ComparisonResult.match - case (.p_appleSignFullName_set(let left),.p_appleSignFullName_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignEmail_get,.p_appleSignEmail_get): return Matcher.ComparisonResult.match - case (.p_appleSignEmail_set(let left),.p_appleSignEmail_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_cookiesDate_get,.p_cookiesDate_get): return Matcher.ComparisonResult.match - case (.p_cookiesDate_set(let left),.p_cookiesDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_reviewLastShownVersion_get,.p_reviewLastShownVersion_get): return Matcher.ComparisonResult.match - case (.p_reviewLastShownVersion_set(let left),.p_reviewLastShownVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastReviewDate_get,.p_lastReviewDate_get): return Matcher.ComparisonResult.match - case (.p_lastReviewDate_set(let left),.p_lastReviewDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_user_get,.p_user_get): return Matcher.ComparisonResult.match - case (.p_user_set(let left),.p_user_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_userSettings_get,.p_userSettings_get): return Matcher.ComparisonResult.match - case (.p_userSettings_set(let left),.p_userSettings_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_resetAppSupportDirectoryUserData_get,.p_resetAppSupportDirectoryUserData_get): return Matcher.ComparisonResult.match - case (.p_resetAppSupportDirectoryUserData_set(let left),.p_resetAppSupportDirectoryUserData_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_useRelativeDates_get,.p_useRelativeDates_get): return Matcher.ComparisonResult.match - case (.p_useRelativeDates_set(let left),.p_useRelativeDates_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastUsedSocialAuth_get,.p_lastUsedSocialAuth_get): return Matcher.ComparisonResult.match - case (.p_lastUsedSocialAuth_set(let left),.p_lastUsedSocialAuth_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_latestAvailableAppVersion_get,.p_latestAvailableAppVersion_get): return Matcher.ComparisonResult.match - case (.p_latestAvailableAppVersion_set(let left),.p_latestAvailableAppVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_updateAppRequired_get,.p_updateAppRequired_get): return Matcher.ComparisonResult.match - case (.p_updateAppRequired_set(let left),.p_updateAppRequired_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_clear: return 0 - case .p_accessToken_get: return 0 - case .p_accessToken_set(let newValue): return newValue.intValue - case .p_refreshToken_get: return 0 - case .p_refreshToken_set(let newValue): return newValue.intValue - case .p_pushToken_get: return 0 - case .p_pushToken_set(let newValue): return newValue.intValue - case .p_appleSignFullName_get: return 0 - case .p_appleSignFullName_set(let newValue): return newValue.intValue - case .p_appleSignEmail_get: return 0 - case .p_appleSignEmail_set(let newValue): return newValue.intValue - case .p_cookiesDate_get: return 0 - case .p_cookiesDate_set(let newValue): return newValue.intValue - case .p_reviewLastShownVersion_get: return 0 - case .p_reviewLastShownVersion_set(let newValue): return newValue.intValue - case .p_lastReviewDate_get: return 0 - case .p_lastReviewDate_set(let newValue): return newValue.intValue - case .p_user_get: return 0 - case .p_user_set(let newValue): return newValue.intValue - case .p_userSettings_get: return 0 - case .p_userSettings_set(let newValue): return newValue.intValue - case .p_resetAppSupportDirectoryUserData_get: return 0 - case .p_resetAppSupportDirectoryUserData_set(let newValue): return newValue.intValue - case .p_useRelativeDates_get: return 0 - case .p_useRelativeDates_set(let newValue): return newValue.intValue - case .p_lastUsedSocialAuth_get: return 0 - case .p_lastUsedSocialAuth_set(let newValue): return newValue.intValue - case .p_latestAvailableAppVersion_get: return 0 - case .p_latestAvailableAppVersion_set(let newValue): return newValue.intValue - case .p_updateAppRequired_get: return 0 - case .p_updateAppRequired_set(let newValue): return newValue.intValue - } - } - func assertionName() -> String { - switch self { - case .m_clear: return ".clear()" - case .p_accessToken_get: return "[get] .accessToken" - case .p_accessToken_set: return "[set] .accessToken" - case .p_refreshToken_get: return "[get] .refreshToken" - case .p_refreshToken_set: return "[set] .refreshToken" - case .p_pushToken_get: return "[get] .pushToken" - case .p_pushToken_set: return "[set] .pushToken" - case .p_appleSignFullName_get: return "[get] .appleSignFullName" - case .p_appleSignFullName_set: return "[set] .appleSignFullName" - case .p_appleSignEmail_get: return "[get] .appleSignEmail" - case .p_appleSignEmail_set: return "[set] .appleSignEmail" - case .p_cookiesDate_get: return "[get] .cookiesDate" - case .p_cookiesDate_set: return "[set] .cookiesDate" - case .p_reviewLastShownVersion_get: return "[get] .reviewLastShownVersion" - case .p_reviewLastShownVersion_set: return "[set] .reviewLastShownVersion" - case .p_lastReviewDate_get: return "[get] .lastReviewDate" - case .p_lastReviewDate_set: return "[set] .lastReviewDate" - case .p_user_get: return "[get] .user" - case .p_user_set: return "[set] .user" - case .p_userSettings_get: return "[get] .userSettings" - case .p_userSettings_set: return "[set] .userSettings" - case .p_resetAppSupportDirectoryUserData_get: return "[get] .resetAppSupportDirectoryUserData" - case .p_resetAppSupportDirectoryUserData_set: return "[set] .resetAppSupportDirectoryUserData" - case .p_useRelativeDates_get: return "[get] .useRelativeDates" - case .p_useRelativeDates_set: return "[set] .useRelativeDates" - case .p_lastUsedSocialAuth_get: return "[get] .lastUsedSocialAuth" - case .p_lastUsedSocialAuth_set: return "[set] .lastUsedSocialAuth" - case .p_latestAvailableAppVersion_get: return "[get] .latestAvailableAppVersion" - case .p_latestAvailableAppVersion_set: return "[set] .latestAvailableAppVersion" - case .p_updateAppRequired_get: return "[get] .updateAppRequired" - case .p_updateAppRequired_set: return "[set] .updateAppRequired" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func accessToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_accessToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func refreshToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_refreshToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func pushToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_pushToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignFullName(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignFullName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignEmail(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func cookiesDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_cookiesDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func reviewLastShownVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_reviewLastShownVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastReviewDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_lastReviewDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func user(getter defaultValue: DataLayer.User?...) -> PropertyStub { - return Given(method: .p_user_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func userSettings(getter defaultValue: UserSettings?...) -> PropertyStub { - return Given(method: .p_userSettings_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func resetAppSupportDirectoryUserData(getter defaultValue: Bool?...) -> PropertyStub { - return Given(method: .p_resetAppSupportDirectoryUserData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func useRelativeDates(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_useRelativeDates_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastUsedSocialAuth(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_lastUsedSocialAuth_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func latestAvailableAppVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_latestAvailableAppVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func updateAppRequired(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_updateAppRequired_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func clear() -> Verify { return Verify(method: .m_clear)} - public static var accessToken: Verify { return Verify(method: .p_accessToken_get) } - public static func accessToken(set newValue: Parameter) -> Verify { return Verify(method: .p_accessToken_set(newValue)) } - public static var refreshToken: Verify { return Verify(method: .p_refreshToken_get) } - public static func refreshToken(set newValue: Parameter) -> Verify { return Verify(method: .p_refreshToken_set(newValue)) } - public static var pushToken: Verify { return Verify(method: .p_pushToken_get) } - public static func pushToken(set newValue: Parameter) -> Verify { return Verify(method: .p_pushToken_set(newValue)) } - public static var appleSignFullName: Verify { return Verify(method: .p_appleSignFullName_get) } - public static func appleSignFullName(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignFullName_set(newValue)) } - public static var appleSignEmail: Verify { return Verify(method: .p_appleSignEmail_get) } - public static func appleSignEmail(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignEmail_set(newValue)) } - public static var cookiesDate: Verify { return Verify(method: .p_cookiesDate_get) } - public static func cookiesDate(set newValue: Parameter) -> Verify { return Verify(method: .p_cookiesDate_set(newValue)) } - public static var reviewLastShownVersion: Verify { return Verify(method: .p_reviewLastShownVersion_get) } - public static func reviewLastShownVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_reviewLastShownVersion_set(newValue)) } - public static var lastReviewDate: Verify { return Verify(method: .p_lastReviewDate_get) } - public static func lastReviewDate(set newValue: Parameter) -> Verify { return Verify(method: .p_lastReviewDate_set(newValue)) } - public static var user: Verify { return Verify(method: .p_user_get) } - public static func user(set newValue: Parameter) -> Verify { return Verify(method: .p_user_set(newValue)) } - public static var userSettings: Verify { return Verify(method: .p_userSettings_get) } - public static func userSettings(set newValue: Parameter) -> Verify { return Verify(method: .p_userSettings_set(newValue)) } - public static var resetAppSupportDirectoryUserData: Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_get) } - public static func resetAppSupportDirectoryUserData(set newValue: Parameter) -> Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_set(newValue)) } - public static var useRelativeDates: Verify { return Verify(method: .p_useRelativeDates_get) } - public static func useRelativeDates(set newValue: Parameter) -> Verify { return Verify(method: .p_useRelativeDates_set(newValue)) } - public static var lastUsedSocialAuth: Verify { return Verify(method: .p_lastUsedSocialAuth_get) } - public static func lastUsedSocialAuth(set newValue: Parameter) -> Verify { return Verify(method: .p_lastUsedSocialAuth_set(newValue)) } - public static var latestAvailableAppVersion: Verify { return Verify(method: .p_latestAvailableAppVersion_get) } - public static func latestAvailableAppVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_latestAvailableAppVersion_set(newValue)) } - public static var updateAppRequired: Verify { return Verify(method: .p_updateAppRequired_get) } - public static func updateAppRequired(set newValue: Parameter) -> Verify { return Verify(method: .p_updateAppRequired_set(newValue)) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func clear(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_clear, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CourseStructureManagerProtocol - -open class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getLoadedCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func shiftDueDates(courseID: String) throws { - addInvocation(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - do { - _ = try methodReturnValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - - fileprivate enum MethodType { - case m_getCourseBlocks__courseID_courseID(Parameter) - case m_getLoadedCourseBlocks__courseID_courseID(Parameter) - case m_shiftDueDates__courseID_courseID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseBlocks__courseID_courseID(let lhsCourseid), .m_getCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getLoadedCourseBlocks__courseID_courseID(let lhsCourseid), .m_getLoadedCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_shiftDueDates__courseID_courseID(let lhsCourseid), .m_shiftDueDates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_getLoadedCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_shiftDueDates__courseID_courseID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getCourseBlocks__courseID_courseID: return ".getCourseBlocks(courseID:)" - case .m_getLoadedCourseBlocks__courseID_courseID: return ".getLoadedCourseBlocks(courseID:)" - case .m_shiftDueDates__courseID_courseID: return ".shiftDueDates(courseID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getLoadedCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func shiftDueDates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func shiftDueDates(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseBlocks__courseID_courseID(`courseID`))} - public static func getLoadedCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`))} - public static func shiftDueDates(courseID: Parameter) -> Verify { return Verify(method: .m_shiftDueDates__courseID_courseID(`courseID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func getLoadedCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func shiftDueDates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_shiftDueDates__courseID_courseID(`courseID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DownloadManagerProtocol - -open class DownloadManagerProtocolMock: DownloadManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCurrentDownloadTask() -> DownloadDataTask? { - addInvocation(.m_getCurrentDownloadTask) - let perform = methodPerformValue(.m_getCurrentDownloadTask) as? () -> Void - perform?() - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_getCurrentDownloadTask).casted() - } catch { - // do nothing - } - return __value - } - - open func eventPublisher() -> AnyPublisher { - addInvocation(.m_eventPublisher) - let perform = methodPerformValue(.m_eventPublisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_eventPublisher).casted() - } catch { - onFatalFailure("Stub return value not specified for eventPublisher(). Use given") - Failure("Stub return value not specified for eventPublisher(). Use given") - } - return __value - } - - open func addToDownloadQueue(blocks: [CourseBlock]) throws { - addInvocation(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - do { - _ = try methodReturnValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getDownloadTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasks) - let perform = methodPerformValue(.m_getDownloadTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasks(). Use given") - Failure("Stub return value not specified for getDownloadTasks(). Use given") - } - return __value - } - - open func getDownloadTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func cancelDownloading(courseId: String, blocks: [CourseBlock]) throws { - addInvocation(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) as? (String, [CourseBlock]) -> Void - perform?(`courseId`, `blocks`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(task: DownloadDataTask) throws { - addInvocation(.m_cancelDownloading__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_cancelDownloading__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - do { - _ = try methodReturnValue(.m_cancelDownloading__task_task(Parameter.value(`task`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(courseId: String) throws { - addInvocation(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelAllDownloading() throws { - addInvocation(.m_cancelAllDownloading) - let perform = methodPerformValue(.m_cancelAllDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_cancelAllDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func deleteAll() { - addInvocation(.m_deleteAll) - let perform = methodPerformValue(.m_deleteAll) as? () -> Void - perform?() - } - - open func fileUrl(for blockId: String) -> URL? { - addInvocation(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: URL? = nil - do { - __value = try methodReturnValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func resumeDownloading() throws { - addInvocation(.m_resumeDownloading) - let perform = methodPerformValue(.m_resumeDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_resumeDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func isLargeVideosSize(blocks: [CourseBlock]) -> Bool { - addInvocation(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - Failure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - } - return __value - } - - open func removeAppSupportDirectoryUnusedContent() { - addInvocation(.m_removeAppSupportDirectoryUnusedContent) - let perform = methodPerformValue(.m_removeAppSupportDirectoryUnusedContent) as? () -> Void - perform?() - } - - open func delete(blocks: [CourseBlock], courseId: String) { - addInvocation(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) as? ([CourseBlock], String) -> Void - perform?(`blocks`, `courseId`) - } - - open func downloadTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getFreeDiskSpace() -> Int? { - addInvocation(.m_getFreeDiskSpace) - let perform = methodPerformValue(.m_getFreeDiskSpace) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getFreeDiskSpace).casted() - } catch { - // do nothing - } - return __value - } - - - fileprivate enum MethodType { - case m_getCurrentDownloadTask - case m_eventPublisher - case m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>) - case m_getDownloadTasks - case m_getDownloadTasksForCourse__courseId(Parameter) - case m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter, Parameter<[CourseBlock]>) - case m_cancelDownloading__task_task(Parameter) - case m_cancelDownloading__courseId_courseId(Parameter) - case m_cancelAllDownloading - case m_deleteAll - case m_fileUrl__for_blockId(Parameter) - case m_resumeDownloading - case m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>) - case m_removeAppSupportDirectoryUnusedContent - case m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>, Parameter) - case m_downloadTask__for_blockId(Parameter) - case m_getFreeDiskSpace - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCurrentDownloadTask, .m_getCurrentDownloadTask): return .match - - case (.m_eventPublisher, .m_eventPublisher): return .match - - case (.m_addToDownloadQueue__blocks_blocks(let lhsBlocks), .m_addToDownloadQueue__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadTasks, .m_getDownloadTasks): return .match - - case (.m_getDownloadTasksForCourse__courseId(let lhsCourseid), .m_getDownloadTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseIdblocks_blocks(let lhsCourseid, let lhsBlocks), .m_cancelDownloading__courseId_courseIdblocks_blocks(let rhsCourseid, let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__task_task(let lhsTask), .m_cancelDownloading__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseId(let lhsCourseid), .m_cancelDownloading__courseId_courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelAllDownloading, .m_cancelAllDownloading): return .match - - case (.m_deleteAll, .m_deleteAll): return .match - - case (.m_fileUrl__for_blockId(let lhsBlockid), .m_fileUrl__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_resumeDownloading, .m_resumeDownloading): return .match - - case (.m_isLargeVideosSize__blocks_blocks(let lhsBlocks), .m_isLargeVideosSize__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_removeAppSupportDirectoryUnusedContent, .m_removeAppSupportDirectoryUnusedContent): return .match - - case (.m_delete__blocks_blockscourseId_courseId(let lhsBlocks, let lhsCourseid), .m_delete__blocks_blockscourseId_courseId(let rhsBlocks, let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_downloadTask__for_blockId(let lhsBlockid), .m_downloadTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getFreeDiskSpace, .m_getFreeDiskSpace): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_getCurrentDownloadTask: return 0 - case .m_eventPublisher: return 0 - case let .m_addToDownloadQueue__blocks_blocks(p0): return p0.intValue - case .m_getDownloadTasks: return 0 - case let .m_getDownloadTasksForCourse__courseId(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseIdblocks_blocks(p0, p1): return p0.intValue + p1.intValue - case let .m_cancelDownloading__task_task(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseId(p0): return p0.intValue - case .m_cancelAllDownloading: return 0 - case .m_deleteAll: return 0 - case let .m_fileUrl__for_blockId(p0): return p0.intValue - case .m_resumeDownloading: return 0 - case let .m_isLargeVideosSize__blocks_blocks(p0): return p0.intValue - case .m_removeAppSupportDirectoryUnusedContent: return 0 - case let .m_delete__blocks_blockscourseId_courseId(p0, p1): return p0.intValue + p1.intValue - case let .m_downloadTask__for_blockId(p0): return p0.intValue - case .m_getFreeDiskSpace: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_getCurrentDownloadTask: return ".getCurrentDownloadTask()" - case .m_eventPublisher: return ".eventPublisher()" - case .m_addToDownloadQueue__blocks_blocks: return ".addToDownloadQueue(blocks:)" - case .m_getDownloadTasks: return ".getDownloadTasks()" - case .m_getDownloadTasksForCourse__courseId: return ".getDownloadTasksForCourse(_:)" - case .m_cancelDownloading__courseId_courseIdblocks_blocks: return ".cancelDownloading(courseId:blocks:)" - case .m_cancelDownloading__task_task: return ".cancelDownloading(task:)" - case .m_cancelDownloading__courseId_courseId: return ".cancelDownloading(courseId:)" - case .m_cancelAllDownloading: return ".cancelAllDownloading()" - case .m_deleteAll: return ".deleteAll()" - case .m_fileUrl__for_blockId: return ".fileUrl(for:)" - case .m_resumeDownloading: return ".resumeDownloading()" - case .m_isLargeVideosSize__blocks_blocks: return ".isLargeVideosSize(blocks:)" - case .m_removeAppSupportDirectoryUnusedContent: return ".removeAppSupportDirectoryUnusedContent()" - case .m_delete__blocks_blockscourseId_courseId: return ".delete(blocks:courseId:)" - case .m_downloadTask__for_blockId: return ".downloadTask(for:)" - case .m_getFreeDiskSpace: return ".getFreeDiskSpace()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCurrentDownloadTask(willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func eventPublisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func fileUrl(for blockId: Parameter, willReturn: URL?...) -> MethodStub { - return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getFreeDiskSpace(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCurrentDownloadTask(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func eventPublisher(willProduce: (Stubber>) -> Void) -> MethodStub { - let willReturn: [AnyPublisher] = [] - let given: Given = { return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - public static func getDownloadTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func fileUrl(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [URL?] = [] - let given: Given = { return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (URL?).self) - willProduce(stubber) - return given - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func downloadTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getFreeDiskSpace(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(task: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(task: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelAllDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelAllDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func resumeDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resumeDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCurrentDownloadTask() -> Verify { return Verify(method: .m_getCurrentDownloadTask)} - public static func eventPublisher() -> Verify { return Verify(method: .m_eventPublisher)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocks(`blocks`))} - public static func getDownloadTasks() -> Verify { return Verify(method: .m_getDownloadTasks)} - public static func getDownloadTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadTasksForCourse__courseId(`courseId`))} - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`))} - public static func cancelDownloading(task: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__task_task(`task`))} - public static func cancelDownloading(courseId: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseId(`courseId`))} - public static func cancelAllDownloading() -> Verify { return Verify(method: .m_cancelAllDownloading)} - public static func deleteAll() -> Verify { return Verify(method: .m_deleteAll)} - public static func fileUrl(for blockId: Parameter) -> Verify { return Verify(method: .m_fileUrl__for_blockId(`blockId`))} - public static func resumeDownloading() -> Verify { return Verify(method: .m_resumeDownloading)} - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_isLargeVideosSize__blocks_blocks(`blocks`))} - public static func removeAppSupportDirectoryUnusedContent() -> Verify { return Verify(method: .m_removeAppSupportDirectoryUnusedContent)} - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter) -> Verify { return Verify(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`))} - public static func downloadTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadTask__for_blockId(`blockId`))} - public static func getFreeDiskSpace() -> Verify { return Verify(method: .m_getFreeDiskSpace)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCurrentDownloadTask(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getCurrentDownloadTask, performs: perform) - } - public static func eventPublisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_eventPublisher, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), performs: perform) - } - public static func getDownloadTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadTasks, performs: perform) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, perform: @escaping (String, [CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), performs: perform) - } - public static func cancelDownloading(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__task_task(`task`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseId(`courseId`), performs: perform) - } - public static func cancelAllDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_cancelAllDownloading, performs: perform) - } - public static func deleteAll(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAll, performs: perform) - } - public static func fileUrl(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_fileUrl__for_blockId(`blockId`), performs: perform) - } - public static func resumeDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_resumeDownloading, performs: perform) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), performs: perform) - } - public static func removeAppSupportDirectoryUnusedContent(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeAppSupportDirectoryUnusedContent, performs: perform) - } - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter, perform: @escaping ([CourseBlock], String) -> Void) -> Perform { - return Perform(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`), performs: perform) - } - public static func downloadTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadTask__for_blockId(`blockId`), performs: perform) - } - public static func getFreeDiskSpace(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getFreeDiskSpace, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DownloadsAnalytics - -open class DownloadsAnalyticsMock: DownloadsAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func downloadCourseClicked(courseId: String, courseName: String) { - addInvocation(.m_downloadCourseClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_downloadCourseClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func cancelDownloadClicked(courseId: String, courseName: String) { - addInvocation(.m_cancelDownloadClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_cancelDownloadClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func removeDownloadClicked(courseId: String, courseName: String) { - addInvocation(.m_removeDownloadClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_removeDownloadClicked__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func downloadConfirmed(courseId: String, courseName: String, downloadSize: Int64) { - addInvocation(.m_downloadConfirmed__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`downloadSize`))) - let perform = methodPerformValue(.m_downloadConfirmed__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`downloadSize`))) as? (String, String, Int64) -> Void - perform?(`courseId`, `courseName`, `downloadSize`) - } - - open func downloadCancelled(courseId: String, courseName: String) { - addInvocation(.m_downloadCancelled__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) - let perform = methodPerformValue(.m_downloadCancelled__courseId_courseIdcourseName_courseName(Parameter.value(`courseId`), Parameter.value(`courseName`))) as? (String, String) -> Void - perform?(`courseId`, `courseName`) - } - - open func downloadRemoved(courseId: String, courseName: String, downloadSize: Int64) { - addInvocation(.m_downloadRemoved__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`downloadSize`))) - let perform = methodPerformValue(.m_downloadRemoved__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`downloadSize`))) as? (String, String, Int64) -> Void - perform?(`courseId`, `courseName`, `downloadSize`) - } - - open func downloadError(courseId: String, courseName: String, errorType: String) { - addInvocation(.m_downloadError__courseId_courseIdcourseName_courseNameerrorType_errorType(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`errorType`))) - let perform = methodPerformValue(.m_downloadError__courseId_courseIdcourseName_courseNameerrorType_errorType(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`errorType`))) as? (String, String, String) -> Void - perform?(`courseId`, `courseName`, `errorType`) - } - - open func downloadCompleted(courseId: String, courseName: String, downloadSize: Int64) { - addInvocation(.m_downloadCompleted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`downloadSize`))) - let perform = methodPerformValue(.m_downloadCompleted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`downloadSize`))) as? (String, String, Int64) -> Void - perform?(`courseId`, `courseName`, `downloadSize`) - } - - open func downloadStarted(courseId: String, courseName: String, downloadSize: Int64) { - addInvocation(.m_downloadStarted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`downloadSize`))) - let perform = methodPerformValue(.m_downloadStarted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(Parameter.value(`courseId`), Parameter.value(`courseName`), Parameter.value(`downloadSize`))) as? (String, String, Int64) -> Void - perform?(`courseId`, `courseName`, `downloadSize`) - } - - open func downloadsScreenViewed() { - addInvocation(.m_downloadsScreenViewed) - let perform = methodPerformValue(.m_downloadsScreenViewed) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_downloadCourseClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_cancelDownloadClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_removeDownloadClicked__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_downloadConfirmed__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(Parameter, Parameter, Parameter) - case m_downloadCancelled__courseId_courseIdcourseName_courseName(Parameter, Parameter) - case m_downloadRemoved__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(Parameter, Parameter, Parameter) - case m_downloadError__courseId_courseIdcourseName_courseNameerrorType_errorType(Parameter, Parameter, Parameter) - case m_downloadCompleted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(Parameter, Parameter, Parameter) - case m_downloadStarted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(Parameter, Parameter, Parameter) - case m_downloadsScreenViewed - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_downloadCourseClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_downloadCourseClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloadClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_cancelDownloadClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_removeDownloadClicked__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_removeDownloadClicked__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_downloadConfirmed__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(let lhsCourseid, let lhsCoursename, let lhsDownloadsize), .m_downloadConfirmed__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(let rhsCourseid, let rhsCoursename, let rhsDownloadsize)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadsize, rhs: rhsDownloadsize, with: matcher), lhsDownloadsize, rhsDownloadsize, "downloadSize")) - return Matcher.ComparisonResult(results) - - case (.m_downloadCancelled__courseId_courseIdcourseName_courseName(let lhsCourseid, let lhsCoursename), .m_downloadCancelled__courseId_courseIdcourseName_courseName(let rhsCourseid, let rhsCoursename)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - return Matcher.ComparisonResult(results) - - case (.m_downloadRemoved__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(let lhsCourseid, let lhsCoursename, let lhsDownloadsize), .m_downloadRemoved__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(let rhsCourseid, let rhsCoursename, let rhsDownloadsize)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadsize, rhs: rhsDownloadsize, with: matcher), lhsDownloadsize, rhsDownloadsize, "downloadSize")) - return Matcher.ComparisonResult(results) - - case (.m_downloadError__courseId_courseIdcourseName_courseNameerrorType_errorType(let lhsCourseid, let lhsCoursename, let lhsErrortype), .m_downloadError__courseId_courseIdcourseName_courseNameerrorType_errorType(let rhsCourseid, let rhsCoursename, let rhsErrortype)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsErrortype, rhs: rhsErrortype, with: matcher), lhsErrortype, rhsErrortype, "errorType")) - return Matcher.ComparisonResult(results) - - case (.m_downloadCompleted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(let lhsCourseid, let lhsCoursename, let lhsDownloadsize), .m_downloadCompleted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(let rhsCourseid, let rhsCoursename, let rhsDownloadsize)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadsize, rhs: rhsDownloadsize, with: matcher), lhsDownloadsize, rhsDownloadsize, "downloadSize")) - return Matcher.ComparisonResult(results) - - case (.m_downloadStarted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(let lhsCourseid, let lhsCoursename, let lhsDownloadsize), .m_downloadStarted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(let rhsCourseid, let rhsCoursename, let rhsDownloadsize)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadsize, rhs: rhsDownloadsize, with: matcher), lhsDownloadsize, rhsDownloadsize, "downloadSize")) - return Matcher.ComparisonResult(results) - - case (.m_downloadsScreenViewed, .m_downloadsScreenViewed): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_downloadCourseClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_cancelDownloadClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_removeDownloadClicked__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_downloadConfirmed__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_downloadCancelled__courseId_courseIdcourseName_courseName(p0, p1): return p0.intValue + p1.intValue - case let .m_downloadRemoved__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_downloadError__courseId_courseIdcourseName_courseNameerrorType_errorType(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_downloadCompleted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_downloadStarted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case .m_downloadsScreenViewed: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_downloadCourseClicked__courseId_courseIdcourseName_courseName: return ".downloadCourseClicked(courseId:courseName:)" - case .m_cancelDownloadClicked__courseId_courseIdcourseName_courseName: return ".cancelDownloadClicked(courseId:courseName:)" - case .m_removeDownloadClicked__courseId_courseIdcourseName_courseName: return ".removeDownloadClicked(courseId:courseName:)" - case .m_downloadConfirmed__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize: return ".downloadConfirmed(courseId:courseName:downloadSize:)" - case .m_downloadCancelled__courseId_courseIdcourseName_courseName: return ".downloadCancelled(courseId:courseName:)" - case .m_downloadRemoved__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize: return ".downloadRemoved(courseId:courseName:downloadSize:)" - case .m_downloadError__courseId_courseIdcourseName_courseNameerrorType_errorType: return ".downloadError(courseId:courseName:errorType:)" - case .m_downloadCompleted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize: return ".downloadCompleted(courseId:courseName:downloadSize:)" - case .m_downloadStarted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize: return ".downloadStarted(courseId:courseName:downloadSize:)" - case .m_downloadsScreenViewed: return ".downloadsScreenViewed()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func downloadCourseClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_downloadCourseClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func cancelDownloadClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_cancelDownloadClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func removeDownloadClicked(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_removeDownloadClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func downloadConfirmed(courseId: Parameter, courseName: Parameter, downloadSize: Parameter) -> Verify { return Verify(method: .m_downloadConfirmed__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(`courseId`, `courseName`, `downloadSize`))} - public static func downloadCancelled(courseId: Parameter, courseName: Parameter) -> Verify { return Verify(method: .m_downloadCancelled__courseId_courseIdcourseName_courseName(`courseId`, `courseName`))} - public static func downloadRemoved(courseId: Parameter, courseName: Parameter, downloadSize: Parameter) -> Verify { return Verify(method: .m_downloadRemoved__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(`courseId`, `courseName`, `downloadSize`))} - public static func downloadError(courseId: Parameter, courseName: Parameter, errorType: Parameter) -> Verify { return Verify(method: .m_downloadError__courseId_courseIdcourseName_courseNameerrorType_errorType(`courseId`, `courseName`, `errorType`))} - public static func downloadCompleted(courseId: Parameter, courseName: Parameter, downloadSize: Parameter) -> Verify { return Verify(method: .m_downloadCompleted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(`courseId`, `courseName`, `downloadSize`))} - public static func downloadStarted(courseId: Parameter, courseName: Parameter, downloadSize: Parameter) -> Verify { return Verify(method: .m_downloadStarted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(`courseId`, `courseName`, `downloadSize`))} - public static func downloadsScreenViewed() -> Verify { return Verify(method: .m_downloadsScreenViewed)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func downloadCourseClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_downloadCourseClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func cancelDownloadClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_cancelDownloadClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func removeDownloadClicked(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_removeDownloadClicked__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func downloadConfirmed(courseId: Parameter, courseName: Parameter, downloadSize: Parameter, perform: @escaping (String, String, Int64) -> Void) -> Perform { - return Perform(method: .m_downloadConfirmed__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(`courseId`, `courseName`, `downloadSize`), performs: perform) - } - public static func downloadCancelled(courseId: Parameter, courseName: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_downloadCancelled__courseId_courseIdcourseName_courseName(`courseId`, `courseName`), performs: perform) - } - public static func downloadRemoved(courseId: Parameter, courseName: Parameter, downloadSize: Parameter, perform: @escaping (String, String, Int64) -> Void) -> Perform { - return Perform(method: .m_downloadRemoved__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(`courseId`, `courseName`, `downloadSize`), performs: perform) - } - public static func downloadError(courseId: Parameter, courseName: Parameter, errorType: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_downloadError__courseId_courseIdcourseName_courseNameerrorType_errorType(`courseId`, `courseName`, `errorType`), performs: perform) - } - public static func downloadCompleted(courseId: Parameter, courseName: Parameter, downloadSize: Parameter, perform: @escaping (String, String, Int64) -> Void) -> Perform { - return Perform(method: .m_downloadCompleted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(`courseId`, `courseName`, `downloadSize`), performs: perform) - } - public static func downloadStarted(courseId: Parameter, courseName: Parameter, downloadSize: Parameter, perform: @escaping (String, String, Int64) -> Void) -> Perform { - return Perform(method: .m_downloadStarted__courseId_courseIdcourseName_courseNamedownloadSize_downloadSize(`courseId`, `courseName`, `downloadSize`), performs: perform) - } - public static func downloadsScreenViewed(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_downloadsScreenViewed, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DownloadsHelperProtocol - -open class DownloadsHelperProtocolMock: DownloadsHelperProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func calculateDownloadProgress(courseID: String) -> (downloaded: Int, total: Int) { - addInvocation(.m_calculateDownloadProgress__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_calculateDownloadProgress__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: (downloaded: Int, total: Int) - do { - __value = try methodReturnValue(.m_calculateDownloadProgress__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for calculateDownloadProgress(courseID: String). Use given") - Failure("Stub return value not specified for calculateDownloadProgress(courseID: String). Use given") - } - return __value - } - - open func isDownloading(courseID: String) -> Bool { - addInvocation(.m_isDownloading__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_isDownloading__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isDownloading__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isDownloading(courseID: String). Use given") - Failure("Stub return value not specified for isDownloading(courseID: String). Use given") - } - return __value - } - - open func isFullyDownloaded(courseID: String) -> Bool { - addInvocation(.m_isFullyDownloaded__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_isFullyDownloaded__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isFullyDownloaded__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isFullyDownloaded(courseID: String). Use given") - Failure("Stub return value not specified for isFullyDownloaded(courseID: String). Use given") - } - return __value - } - - open func getDownloadTasksForCourse(courseID: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasksForCourse__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getDownloadTasksForCourse__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasksForCourse__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasksForCourse(courseID: String). Use given") - Failure("Stub return value not specified for getDownloadTasksForCourse(courseID: String). Use given") - } - return __value - } - - - fileprivate enum MethodType { - case m_calculateDownloadProgress__courseID_courseID(Parameter) - case m_isDownloading__courseID_courseID(Parameter) - case m_isFullyDownloaded__courseID_courseID(Parameter) - case m_getDownloadTasksForCourse__courseID_courseID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_calculateDownloadProgress__courseID_courseID(let lhsCourseid), .m_calculateDownloadProgress__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_isDownloading__courseID_courseID(let lhsCourseid), .m_isDownloading__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_isFullyDownloaded__courseID_courseID(let lhsCourseid), .m_isFullyDownloaded__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadTasksForCourse__courseID_courseID(let lhsCourseid), .m_getDownloadTasksForCourse__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_calculateDownloadProgress__courseID_courseID(p0): return p0.intValue - case let .m_isDownloading__courseID_courseID(p0): return p0.intValue - case let .m_isFullyDownloaded__courseID_courseID(p0): return p0.intValue - case let .m_getDownloadTasksForCourse__courseID_courseID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_calculateDownloadProgress__courseID_courseID: return ".calculateDownloadProgress(courseID:)" - case .m_isDownloading__courseID_courseID: return ".isDownloading(courseID:)" - case .m_isFullyDownloaded__courseID_courseID: return ".isFullyDownloaded(courseID:)" - case .m_getDownloadTasksForCourse__courseID_courseID: return ".getDownloadTasksForCourse(courseID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func calculateDownloadProgress(courseID: Parameter, willReturn: (downloaded: Int, total: Int)...) -> MethodStub { - return Given(method: .m_calculateDownloadProgress__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isDownloading(courseID: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isDownloading__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isFullyDownloaded(courseID: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isFullyDownloaded__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasksForCourse(courseID: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasksForCourse__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func calculateDownloadProgress(courseID: Parameter, willProduce: (Stubber<(downloaded: Int, total: Int)>) -> Void) -> MethodStub { - let willReturn: [(downloaded: Int, total: Int)] = [] - let given: Given = { return Given(method: .m_calculateDownloadProgress__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ((downloaded: Int, total: Int)).self) - willProduce(stubber) - return given - } - public static func isDownloading(courseID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isDownloading__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func isFullyDownloaded(courseID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isFullyDownloaded__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func getDownloadTasksForCourse(courseID: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasksForCourse__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func calculateDownloadProgress(courseID: Parameter) -> Verify { return Verify(method: .m_calculateDownloadProgress__courseID_courseID(`courseID`))} - public static func isDownloading(courseID: Parameter) -> Verify { return Verify(method: .m_isDownloading__courseID_courseID(`courseID`))} - public static func isFullyDownloaded(courseID: Parameter) -> Verify { return Verify(method: .m_isFullyDownloaded__courseID_courseID(`courseID`))} - public static func getDownloadTasksForCourse(courseID: Parameter) -> Verify { return Verify(method: .m_getDownloadTasksForCourse__courseID_courseID(`courseID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func calculateDownloadProgress(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_calculateDownloadProgress__courseID_courseID(`courseID`), performs: perform) - } - public static func isDownloading(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_isDownloading__courseID_courseID(`courseID`), performs: perform) - } - public static func isFullyDownloaded(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_isFullyDownloaded__courseID_courseID(`courseID`), performs: perform) - } - public static func getDownloadTasksForCourse(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadTasksForCourse__courseID_courseID(`courseID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DownloadsInteractorProtocol - -open class DownloadsInteractorProtocolMock: DownloadsInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getDownloadCourses() throws -> [DownloadCoursePreview] { - addInvocation(.m_getDownloadCourses) - let perform = methodPerformValue(.m_getDownloadCourses) as? () -> Void - perform?() - var __value: [DownloadCoursePreview] - do { - __value = try methodReturnValue(.m_getDownloadCourses).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getDownloadCourses(). Use given") - Failure("Stub return value not specified for getDownloadCourses(). Use given") - } catch { - throw error - } - return __value - } - - open func getDownloadCoursesOffline() throws -> [DownloadCoursePreview] { - addInvocation(.m_getDownloadCoursesOffline) - let perform = methodPerformValue(.m_getDownloadCoursesOffline) as? () -> Void - perform?() - var __value: [DownloadCoursePreview] - do { - __value = try methodReturnValue(.m_getDownloadCoursesOffline).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getDownloadCoursesOffline(). Use given") - Failure("Stub return value not specified for getDownloadCoursesOffline(). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_getDownloadCourses - case m_getDownloadCoursesOffline - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getDownloadCourses, .m_getDownloadCourses): return .match - - case (.m_getDownloadCoursesOffline, .m_getDownloadCoursesOffline): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_getDownloadCourses: return 0 - case .m_getDownloadCoursesOffline: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_getDownloadCourses: return ".getDownloadCourses()" - case .m_getDownloadCoursesOffline: return ".getDownloadCoursesOffline()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getDownloadCourses(willReturn: [DownloadCoursePreview]...) -> MethodStub { - return Given(method: .m_getDownloadCourses, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadCoursesOffline(willReturn: [DownloadCoursePreview]...) -> MethodStub { - return Given(method: .m_getDownloadCoursesOffline, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadCourses(willThrow: Error...) -> MethodStub { - return Given(method: .m_getDownloadCourses, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getDownloadCourses(willProduce: (StubberThrows<[DownloadCoursePreview]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getDownloadCourses, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([DownloadCoursePreview]).self) - willProduce(stubber) - return given - } - public static func getDownloadCoursesOffline(willThrow: Error...) -> MethodStub { - return Given(method: .m_getDownloadCoursesOffline, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getDownloadCoursesOffline(willProduce: (StubberThrows<[DownloadCoursePreview]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getDownloadCoursesOffline, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([DownloadCoursePreview]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getDownloadCourses() -> Verify { return Verify(method: .m_getDownloadCourses)} - public static func getDownloadCoursesOffline() -> Verify { return Verify(method: .m_getDownloadCoursesOffline)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getDownloadCourses(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadCourses, performs: perform) - } - public static func getDownloadCoursesOffline(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadCoursesOffline, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - OfflineSyncInteractorProtocol - -open class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func submitOfflineProgress(courseID: String, blockID: String, data: String) throws -> Bool { - addInvocation(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) - let perform = methodPerformValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) as? (String, String, String) -> Void - perform?(`courseID`, `blockID`, `data`) - var __value: Bool - do { - __value = try methodReturnValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - Failure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter, Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let lhsCourseid, let lhsBlockid, let lhsData), .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let rhsCourseid, let rhsBlockid, let rhsData)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsData, rhs: rhsData, with: matcher), lhsData, rhsData, "data")) - return Matcher.ComparisonResult(results) - } - } - - func intValue() -> Int { - switch self { - case let .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data: return ".submitOfflineProgress(courseID:blockID:data:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter) -> Verify { return Verify(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - diff --git a/Downloads/DownloadsTests/DownloadsTests.swift b/Downloads/DownloadsTests/DownloadsTests.swift index 5c618031a..6579eb079 100644 --- a/Downloads/DownloadsTests/DownloadsTests.swift +++ b/Downloads/DownloadsTests/DownloadsTests.swift @@ -7,14 +7,13 @@ import XCTest import Combine -import SwiftyMocky import OEXFoundation @testable import Downloads @testable import Core @MainActor final class DownloadsTests: XCTestCase { - + var downloadsInteractor: DownloadsInteractorProtocolMock! var courseManager: CourseStructureManagerProtocolMock! var downloadManager: DownloadManagerProtocolMock! @@ -23,7 +22,7 @@ final class DownloadsTests: XCTestCase { var router: DownloadsRouterMock! var viewModel: AppDownloadsViewModel! var cancellables: Set! - + override func setUpWithError() throws { downloadsInteractor = DownloadsInteractorProtocolMock() courseManager = CourseStructureManagerProtocolMock() @@ -32,21 +31,25 @@ final class DownloadsTests: XCTestCase { downloadsHelper = DownloadsHelperProtocolMock() router = DownloadsRouterMock() cancellables = Set() - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(connectivity, .isMobileData(getter: false)) - Given(connectivity, .internetReachableSubject(getter: .init(.reachable))) - Given(downloadManager, .eventPublisher(willReturn: PassthroughSubject().eraseToAnyPublisher())) - - Given(downloadsHelper, .calculateDownloadProgress(courseID: .any, willReturn: (0, 0))) - Given(downloadsHelper, .isDownloading(courseID: .any, willReturn: false)) - Given(downloadsHelper, .isFullyDownloaded(courseID: .any, willReturn: false)) - Given(downloadsHelper, .getDownloadTasksForCourse(courseID: .any, willReturn: [])) - Given(courseManager, .getLoadedCourseBlocks(courseID: .any, willReturn: createMockCourseStructure())) - Given(courseManager, .getCourseBlocks(courseID: .any, willReturn: createMockCourseStructure())) - Given(downloadManager, .getFreeDiskSpace(willReturn: 1000000000)) // 1GB free space - Given(downloadManager, .isLargeVideosSize(blocks: .any, willReturn: false)) - + + connectivity.isInternetAvaliable = true + connectivity.isMobileData = false + connectivity.internetReachableSubject = .init(.reachable) + downloadManager.eventPublisherHandler = { + PassthroughSubject().eraseToAnyPublisher() + } + + downloadsHelper.calculateDownloadProgressHandler = { _ in (0, 0) } + downloadsHelper.isDownloadingHandler = { _ in false } + downloadsHelper.isFullyDownloadedHandler = { _ in false } + downloadsHelper.getDownloadTasksForCourseHandler = { _ in [] } + + let mockCourseStructure = createMockCourseStructure() + courseManager.getLoadedCourseBlocksHandler = { _ in mockCourseStructure } + courseManager.getCourseBlocksHandler = { _ in mockCourseStructure } + downloadManager.getFreeDiskSpaceHandler = { 1000000000 } // 1GB free space + downloadManager.isLargeVideosSizeHandler = { _ in false } + viewModel = AppDownloadsViewModel( interactor: DownloadsInteractor(repository: DownloadsRepositoryMock()), courseManager: courseManager, @@ -58,7 +61,7 @@ final class DownloadsTests: XCTestCase { analytics: DownloadsAnalyticsMock() ) } - + override func tearDownWithError() throws { downloadsInteractor = nil courseManager = nil @@ -69,21 +72,21 @@ final class DownloadsTests: XCTestCase { viewModel = nil cancellables = nil } - + // MARK: - Test Getting Download Courses - + func testGetDownloadCourses_WhenOnline_ShouldFetchCoursesFromNetwork() async throws { // Given let expectedCourses = [ createMockDownloadCoursePreview(id: "course0"), createMockDownloadCoursePreview(id: "course1") ] - + let analytics = DownloadsAnalyticsMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(downloadsInteractor, .getDownloadCourses(willReturn: expectedCourses)) - + + connectivity.isInternetAvaliable = true + downloadsInteractor.getDownloadCoursesHandler = { expectedCourses } + viewModel = AppDownloadsViewModel( interactor: downloadsInteractor, courseManager: courseManager, @@ -94,47 +97,55 @@ final class DownloadsTests: XCTestCase { storage: DownloadsStorageMock(), analytics: analytics ) - + // When await viewModel.getDownloadCourses() - + // Then - Verify(downloadsInteractor, 1, .getDownloadCourses()) - Verify(analytics, 1, .downloadsScreenViewed()) + XCTAssertEqual(downloadsInteractor.getDownloadCoursesCallCount, 1) + XCTAssertEqual(analytics.downloadsScreenViewedCallCount, 1) XCTAssertEqual(viewModel.courses.count, 2) XCTAssertEqual(viewModel.courses[0].id, "course0") XCTAssertEqual(viewModel.courses[1].id, "course1") } - + func testRefreshDownloadStates_ShouldUpdateDownloadStates() async { // Given let courses = [ createMockDownloadCoursePreview(id: "course1"), createMockDownloadCoursePreview(id: "course2") ] - + let downloadsInteractor = DownloadsInteractorProtocolMock() - Given(downloadsInteractor, .getDownloadCourses(willReturn: courses)) - Given(downloadsInteractor, .getDownloadCoursesOffline(willReturn: courses)) - + downloadsInteractor.getDownloadCoursesHandler = { courses } + downloadsInteractor.getDownloadCoursesOfflineHandler = { courses } + let task1 = createMockDownloadTask( courseId: "course1", state: .finished, fileSize: 100, actualSize: 100 ) - + // Setup mocks with specific values - Given(downloadsHelper, .calculateDownloadProgress(courseID: .value("course1"), willReturn: (100, 100))) - Given(downloadsHelper, .isDownloading(courseID: .value("course1"), willReturn: false)) - Given(downloadsHelper, .isFullyDownloaded(courseID: .value("course1"), willReturn: true)) - Given(downloadsHelper, .getDownloadTasksForCourse(courseID: .value("course1"), willReturn: [task1])) - - Given(downloadsHelper, .calculateDownloadProgress(courseID: .value("course2"), willReturn: (50, 100))) - Given(downloadsHelper, .isDownloading(courseID: .value("course2"), willReturn: true)) - Given(downloadsHelper, .isFullyDownloaded(courseID: .value("course2"), willReturn: false)) - Given(courseManager, .getLoadedCourseBlocks(courseID: .any, willThrow: NoCachedDataError())) - + downloadsHelper.calculateDownloadProgressHandler = { courseID in + if courseID == "course1" { + return (100, 100) + } else { + return (50, 100) + } + } + downloadsHelper.isDownloadingHandler = { courseID in + return courseID == "course2" + } + downloadsHelper.isFullyDownloadedHandler = { courseID in + return courseID == "course1" + } + downloadsHelper.getDownloadTasksForCourseHandler = { courseID in + return courseID == "course1" ? [task1] : [] + } + courseManager.getLoadedCourseBlocksHandler = { _ in throw NoCachedDataError() } + viewModel = AppDownloadsViewModel( interactor: downloadsInteractor, courseManager: courseManager, @@ -145,34 +156,34 @@ final class DownloadsTests: XCTestCase { storage: DownloadsStorageMock(), analytics: DownloadsAnalyticsMock() ) - + viewModel.courses = courses - + await viewModel.refreshDownloadStates() - + // Then - Verify(downloadsHelper, .atLeastOnce, .calculateDownloadProgress(courseID: .value("course1"))) - Verify(downloadsHelper, .atLeastOnce, .calculateDownloadProgress(courseID: .value("course2"))) - + XCTAssertGreaterThanOrEqual(downloadsHelper.calculateDownloadProgressCallCount, 2) + XCTAssertEqual(viewModel.downloadedSizes["course1"], 100) XCTAssertEqual(viewModel.downloadStates["course2"], .inProgress) } - + // MARK: - Test Download Course - + func testDownloadCourse_WhenCourseStructureAvailable_ShouldAddToDownloadQueue() async throws { // Given let courseID = "course1" let courseStructure = createMockCourseStructure(withDownloadableBlocks: true) let analytics = DownloadsAnalyticsMock() let expectation = XCTestExpectation(description: "Download course completed") - Given(courseManager, .getLoadedCourseBlocks(courseID: .value(courseID), willReturn: courseStructure)) - Given(downloadManager, .getFreeDiskSpace(willReturn: 1000000000)) // 1GB free space - Given(downloadManager, .isLargeVideosSize(blocks: .any, willReturn: false)) - Perform(downloadManager, .addToDownloadQueue(blocks: .any, perform: { _ in + + courseManager.getLoadedCourseBlocksHandler = { _ in courseStructure } + downloadManager.getFreeDiskSpaceHandler = { 1000000000 } // 1GB free space + downloadManager.isLargeVideosSizeHandler = { _ in false } + downloadManager.addToDownloadQueueHandler = { _ in expectation.fulfill() - })) - + } + viewModel = AppDownloadsViewModel( interactor: DownloadsInteractor(repository: DownloadsRepositoryMock()), courseManager: courseManager, @@ -183,32 +194,32 @@ final class DownloadsTests: XCTestCase { storage: DownloadsStorageMock(), analytics: analytics ) - + // When await viewModel.downloadCourse(courseID: courseID) await fulfillment(of: [expectation]) - + // Then - Verify(downloadManager, 1, .addToDownloadQueue(blocks: .any)) - Verify(analytics, 1, .downloadCourseClicked(courseId: .value(courseID), courseName: .any)) - Verify(analytics, 1, .downloadStarted(courseId: .value(courseID), courseName: .any, downloadSize: .any)) + XCTAssertEqual(downloadManager.addToDownloadQueueCallCount, 1) + XCTAssertEqual(analytics.downloadCourseClickedCallCount, 1) + XCTAssertEqual(analytics.downloadStartedCallCount, 1) } - + func testDownloadCourse_WhenNoCachedData_ShouldFetchFromNetwork() async throws { // Given let courseID = "course1" let courseStructure = createMockCourseStructure(withDownloadableBlocks: true) let analytics = DownloadsAnalyticsMock() let expectation = XCTestExpectation(description: "Download course completed") - - Given(courseManager, .getLoadedCourseBlocks(courseID: .value(courseID), willThrow: NoCachedDataError())) - Given(courseManager, .getCourseBlocks(courseID: .value(courseID), willReturn: courseStructure)) - Given(downloadManager, .getFreeDiskSpace(willReturn: 1000000000)) // 1GB free space - Given(downloadManager, .isLargeVideosSize(blocks: .any, willReturn: false)) - Perform(downloadManager, .addToDownloadQueue(blocks: .any, perform: { _ in + + courseManager.getLoadedCourseBlocksHandler = { _ in throw NoCachedDataError() } + courseManager.getCourseBlocksHandler = { _ in courseStructure } + downloadManager.getFreeDiskSpaceHandler = { 1000000000 } // 1GB free space + downloadManager.isLargeVideosSizeHandler = { _ in false } + downloadManager.addToDownloadQueueHandler = { _ in expectation.fulfill() - })) - + } + viewModel = AppDownloadsViewModel( interactor: DownloadsInteractor(repository: DownloadsRepositoryMock()), courseManager: courseManager, @@ -219,34 +230,34 @@ final class DownloadsTests: XCTestCase { storage: DownloadsStorageMock(), analytics: analytics ) - + // When await viewModel.downloadCourse(courseID: courseID) await fulfillment(of: [expectation]) - + // Then - Verify(courseManager, 1, .getCourseBlocks(courseID: .value(courseID))) - Verify(downloadManager, 1, .addToDownloadQueue(blocks: .any)) - Verify(analytics, 1, .downloadCourseClicked(courseId: .value(courseID), courseName: .any)) - Verify(analytics, 1, .downloadStarted(courseId: .value(courseID), courseName: .any, downloadSize: .any)) + XCTAssertEqual(courseManager.getCourseBlocksCallCount, 1) + XCTAssertEqual(downloadManager.addToDownloadQueueCallCount, 1) + XCTAssertEqual(analytics.downloadCourseClickedCallCount, 1) + XCTAssertEqual(analytics.downloadStartedCallCount, 1) XCTAssertEqual(viewModel.downloadStates[courseID], .inProgress) } - + func testDownloadCourse_WhenNoWiFi_ShouldSetErrorMessage() async throws { // Given let courseID = "course1" let courseStructure = createMockCourseStructure(withDownloadableBlocks: true) let analytics = DownloadsAnalyticsMock() let expectation = XCTestExpectation(description: "Download course error") - - Given(courseManager, .getLoadedCourseBlocks(courseID: .value(courseID), willReturn: courseStructure)) - Given(downloadManager, .addToDownloadQueue(blocks: .any, willThrow: NoWiFiError())) - Given(downloadManager, .getFreeDiskSpace(willReturn: 1000000000)) // 1GB free space - Given(downloadManager, .isLargeVideosSize(blocks: .any, willReturn: false)) - Perform(analytics, .downloadError(courseId: .any, courseName: .any, errorType: .any, perform: { _, _, _ in + + courseManager.getLoadedCourseBlocksHandler = { _ in courseStructure } + downloadManager.addToDownloadQueueHandler = { _ in throw NoWiFiError() } + downloadManager.getFreeDiskSpaceHandler = { 1000000000 } // 1GB free space + downloadManager.isLargeVideosSizeHandler = { _ in false } + analytics.downloadErrorHandler = { _, _, _ in expectation.fulfill() - })) - + } + viewModel = AppDownloadsViewModel( interactor: DownloadsInteractor(repository: DownloadsRepositoryMock()), courseManager: courseManager, @@ -257,21 +268,21 @@ final class DownloadsTests: XCTestCase { storage: DownloadsStorageMock(), analytics: analytics ) - + // When await viewModel.downloadCourse(courseID: courseID) await fulfillment(of: [expectation]) - + // Then XCTAssertNotNil(viewModel.errorMessage) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.wifi) - Verify(analytics, 1, .downloadCourseClicked(courseId: .value(courseID), courseName: .any)) - Verify(analytics, 1, .downloadError(courseId: .value(courseID), courseName: .any, errorType: .value("wifi_required"))) + XCTAssertEqual(analytics.downloadCourseClickedCallCount, 1) + XCTAssertEqual(analytics.downloadErrorCallCount, 1) } - + // MARK: - Test Cancel Download - + func testCancelDownload_ShouldCancelAllTasksForCourse() async throws { // Given let courseID = "course1" @@ -279,10 +290,11 @@ final class DownloadsTests: XCTestCase { let secondTask = createMockDownloadTask(id: "task2", courseId: courseID, state: .waiting) let tasks = [secondTask] // Only include the second task, not the current task let analytics = DownloadsAnalyticsMock() - - Given(downloadManager, .getCurrentDownloadTask(willReturn: currentTask)) - Given(downloadManager, .getDownloadTasksForCourse(.value(courseID), willReturn: tasks)) - + + downloadManager.getCurrentDownloadTaskHandler = { currentTask } + downloadManager.getDownloadTasksForCourseHandler = { _ in tasks } + downloadManager.cancelDownloadingTaskHandler = { _ in } + viewModel = AppDownloadsViewModel( interactor: DownloadsInteractor(repository: DownloadsRepositoryMock()), courseManager: courseManager, @@ -293,47 +305,46 @@ final class DownloadsTests: XCTestCase { storage: DownloadsStorageMock(), analytics: analytics ) - + // When await viewModel.cancelDownload(courseID: courseID) - + // Then - Verify(downloadManager, 1, .getCurrentDownloadTask()) - Verify(downloadManager, 1, .getDownloadTasksForCourse(.value(courseID))) - Verify(downloadManager, 1, .cancelDownloading(task: .value(currentTask))) - Verify(downloadManager, 1, .cancelDownloading(task: .value(secondTask))) - Verify(analytics, 1, .cancelDownloadClicked(courseId: .value(courseID), courseName: .any)) - Verify(analytics, 1, .downloadCancelled(courseId: .value(courseID), courseName: .any)) + XCTAssertEqual(downloadManager.getCurrentDownloadTaskCallCount, 1) + XCTAssertEqual(downloadManager.getDownloadTasksForCourseCallCount, 1) + XCTAssertEqual(downloadManager.cancelDownloadingTaskCallCount, 2) + XCTAssertEqual(analytics.cancelDownloadClickedCallCount, 1) + XCTAssertEqual(analytics.downloadCancelledCallCount, 1) } - + // MARK: - Test Remove Download - + func testRemoveDownload_ShouldDeleteFilesForCourse() async throws { // Given let courseID = "course1" let courseStructure = createMockCourseStructure(withDownloadableBlocks: true) let expectation = XCTestExpectation(description: "Remove download completed") - - Given(courseManager, .getLoadedCourseBlocks(courseID: .value(courseID), willReturn: courseStructure)) - - Perform(downloadManager, .delete(blocks: .any, courseId: .any, perform: { _, _ in + + courseManager.getLoadedCourseBlocksHandler = { _ in courseStructure } + + downloadManager.deleteHandler = { _, _ in expectation.fulfill() - })) - + } + // When await viewModel.removeDownload(courseID: courseID, skipConfirmation: true) await fulfillment(of: [expectation]) - + // Then - Verify(courseManager, 1, .getLoadedCourseBlocks(courseID: .value(courseID))) - Verify(downloadManager, 1, .delete(blocks: .any, courseId: .value(courseID))) + XCTAssertGreaterThanOrEqual(courseManager.getLoadedCourseBlocksCallCount, 1) + XCTAssertEqual(downloadManager.deleteCallCount, 1) } - + func testDownloadEvents_FinishedEvent_ShouldMarkAsFinished() async throws { // Given let courseID = "course1" let blockID = "block123" - + let task = createMockDownloadTask( id: "task1", blockId: blockID, @@ -342,29 +353,29 @@ final class DownloadsTests: XCTestCase { fileSize: 100, actualSize: 100 ) - + let subject = PassthroughSubject() let analytics = DownloadsAnalyticsMock() let expectation = XCTestExpectation(description: "Download finished event processed") let mockCourse = createMockDownloadCoursePreview(id: courseID, totalSize: 100) let courseStructure = createMockCourseStructure(withDownloadableBlocks: true) - - Given(downloadManager, .eventPublisher(willReturn: subject.eraseToAnyPublisher())) - - Given(downloadsHelper, .calculateDownloadProgress(courseID: .value(courseID), willReturn: (100, 100))) - Given(downloadsHelper, .isFullyDownloaded(courseID: .value(courseID), willReturn: true)) - Given(courseManager, .getLoadedCourseBlocks(courseID: .value(courseID), willReturn: courseStructure)) - Given(downloadsHelper, .getDownloadTasksForCourse(courseID: .value(courseID), willReturn: [task])) - + + downloadManager.eventPublisherHandler = { subject.eraseToAnyPublisher() } + + downloadsHelper.calculateDownloadProgressHandler = { _ in (100, 100) } + downloadsHelper.isFullyDownloadedHandler = { _ in true } + courseManager.getLoadedCourseBlocksHandler = { _ in courseStructure } + downloadsHelper.getDownloadTasksForCourseHandler = { _ in [task] } + var downloadCompletedCalled = false var downloadCompletedSize: Int64 = 0 - - Perform(analytics, .downloadCompleted(courseId: .any, courseName: .any, downloadSize: .any, perform: { id, name, size in + + analytics.downloadCompletedHandler = { _, _, size in downloadCompletedCalled = true downloadCompletedSize = size expectation.fulfill() - })) - + } + viewModel = AppDownloadsViewModel( interactor: DownloadsInteractor(repository: DownloadsRepositoryMock()), courseManager: courseManager, @@ -375,27 +386,27 @@ final class DownloadsTests: XCTestCase { storage: DownloadsStorageMock(), analytics: analytics ) - + viewModel.courses = [mockCourse] viewModel.downloadStates[courseID] = .inProgress - + // When subject.send(.finished(task)) await fulfillment(of: [expectation]) - + // Then - Verify(downloadsHelper, 1, .getDownloadTasksForCourse(courseID: .value(courseID))) - Verify(downloadsHelper, 1, .isFullyDownloaded(courseID: .value(courseID))) - + XCTAssertGreaterThanOrEqual(downloadsHelper.getDownloadTasksForCourseCallCount, 1) + XCTAssertGreaterThanOrEqual(downloadsHelper.isFullyDownloadedCallCount, 1) + XCTAssertTrue(downloadCompletedCalled, "downloadCompleted should have been called") XCTAssertEqual(downloadCompletedSize, 100, "downloadCompleted should have been called with size 100") - + XCTAssertEqual(viewModel.downloadedSizes[courseID], 100) XCTAssertEqual(viewModel.downloadStates[courseID], .finished) } - + // MARK: - Helper Methods - + private func createMockDownloadCoursePreview( id: String = "test123", name: String = "Test Course", @@ -409,7 +420,7 @@ final class DownloadsTests: XCTestCase { totalSize: totalSize ) } - + private func createMockDownloadTask( id: String = "task1", blockId: String = "block123", @@ -435,7 +446,7 @@ final class DownloadsTests: XCTestCase { actualSize: actualSize ) } - + private func createMockCourseStructure(withDownloadableBlocks: Bool = false) -> CourseStructure { let block = CourseBlock( blockId: "block123", @@ -466,7 +477,7 @@ final class DownloadsTests: XCTestCase { multiDevice: true, offlineDownload: nil ) - + let vertical = CourseVertical( blockId: "vertical1", id: "vertical1", @@ -477,7 +488,7 @@ final class DownloadsTests: XCTestCase { childs: [block], webUrl: "https://test.com" ) - + let sequential = CourseSequential( blockId: "sequential1", id: "sequential1", @@ -488,7 +499,7 @@ final class DownloadsTests: XCTestCase { sequentialProgress: nil, due: nil ) - + let chapter = CourseChapter( blockId: "chapter1", id: "chapter1", @@ -496,7 +507,7 @@ final class DownloadsTests: XCTestCase { type: .chapter, childs: [sequential] ) - + return CourseStructure( id: "course1", graded: false, diff --git a/Downloads/DownloadsTests/Generated/DownloadsMocks.generated.swift b/Downloads/DownloadsTests/Generated/DownloadsMocks.generated.swift new file mode 100644 index 000000000..2d10940fd --- /dev/null +++ b/Downloads/DownloadsTests/Generated/DownloadsMocks.generated.swift @@ -0,0 +1,2034 @@ +/// +/// @Generated by Mockolo +/// + + + +import Alamofire +import Combine +@testable import Core +import CoreData +@testable import Downloads +import Foundation +import OEXFoundation +import SwiftUI +import ZipArchive + + +public final class ConfigProtocolMock: ConfigProtocol, @unchecked Sendable { + public init() { } + public init(baseURL: URL = URL(fileURLWithPath: ""), baseSSOURL: URL = URL(fileURLWithPath: ""), ssoFinishedURL: URL = URL(fileURLWithPath: ""), ssoButtonTitle: [String: Any] = [String: Any](), oAuthClientId: String = "", tokenType: TokenType, feedbackEmail: String = "", appStoreLink: String = "", faq: URL? = nil, platformName: String = "", agreement: AgreementConfig, firebase: FirebaseConfig, facebook: FacebookConfig, microsoft: MicrosoftConfig, google: GoogleConfig, appleSignIn: AppleSignInConfig, features: FeaturesConfig, theme: ThemeConfig, uiComponents: UIComponentsConfig, discovery: DiscoveryConfig, dashboard: DashboardConfig, braze: BrazeConfig, branch: BranchConfig, program: DiscoveryConfig, experimentalFeatures: ExperimentalFeaturesConfig, URIScheme: String = "") { + self.baseURL = baseURL + self.baseSSOURL = baseSSOURL + self.ssoFinishedURL = ssoFinishedURL + self.ssoButtonTitle = ssoButtonTitle + self.oAuthClientId = oAuthClientId + self._tokenType = tokenType + self.feedbackEmail = feedbackEmail + self.appStoreLink = appStoreLink + self.faq = faq + self.platformName = platformName + self._agreement = agreement + self._firebase = firebase + self._facebook = facebook + self._microsoft = microsoft + self._google = google + self._appleSignIn = appleSignIn + self._features = features + self._theme = theme + self._uiComponents = uiComponents + self._discovery = discovery + self._dashboard = dashboard + self._braze = braze + self._branch = branch + self._program = program + self._experimentalFeatures = experimentalFeatures + self.URIScheme = URIScheme + } + + + + public var baseURL: URL = URL(fileURLWithPath: "") + + + public var baseSSOURL: URL = URL(fileURLWithPath: "") + + + public var ssoFinishedURL: URL = URL(fileURLWithPath: "") + + + public var ssoButtonTitle: [String: Any] = [String: Any]() + + + public var oAuthClientId: String = "" + + + private var _tokenType: TokenType! + public var tokenType: TokenType { + get { return _tokenType } + set { _tokenType = newValue } + } + + + public var feedbackEmail: String = "" + + + public var appStoreLink: String = "" + + + public var faq: URL? = nil + + + public var platformName: String = "" + + + private var _agreement: AgreementConfig! + public var agreement: AgreementConfig { + get { return _agreement } + set { _agreement = newValue } + } + + + private var _firebase: FirebaseConfig! + public var firebase: FirebaseConfig { + get { return _firebase } + set { _firebase = newValue } + } + + + private var _facebook: FacebookConfig! + public var facebook: FacebookConfig { + get { return _facebook } + set { _facebook = newValue } + } + + + private var _microsoft: MicrosoftConfig! + public var microsoft: MicrosoftConfig { + get { return _microsoft } + set { _microsoft = newValue } + } + + + private var _google: GoogleConfig! + public var google: GoogleConfig { + get { return _google } + set { _google = newValue } + } + + + private var _appleSignIn: AppleSignInConfig! + public var appleSignIn: AppleSignInConfig { + get { return _appleSignIn } + set { _appleSignIn = newValue } + } + + + private var _features: FeaturesConfig! + public var features: FeaturesConfig { + get { return _features } + set { _features = newValue } + } + + + private var _theme: ThemeConfig! + public var theme: ThemeConfig { + get { return _theme } + set { _theme = newValue } + } + + + private var _uiComponents: UIComponentsConfig! + public var uiComponents: UIComponentsConfig { + get { return _uiComponents } + set { _uiComponents = newValue } + } + + + private var _discovery: DiscoveryConfig! + public var discovery: DiscoveryConfig { + get { return _discovery } + set { _discovery = newValue } + } + + + private var _dashboard: DashboardConfig! + public var dashboard: DashboardConfig { + get { return _dashboard } + set { _dashboard = newValue } + } + + + private var _braze: BrazeConfig! + public var braze: BrazeConfig { + get { return _braze } + set { _braze = newValue } + } + + + private var _branch: BranchConfig! + public var branch: BranchConfig { + get { return _branch } + set { _branch = newValue } + } + + + private var _program: DiscoveryConfig! + public var program: DiscoveryConfig { + get { return _program } + set { _program = newValue } + } + + + private var _experimentalFeatures: ExperimentalFeaturesConfig! + public var experimentalFeatures: ExperimentalFeaturesConfig { + get { return _experimentalFeatures } + set { _experimentalFeatures = newValue } + } + + + public var URIScheme: String = "" +} + +public final class CoreAnalyticsMock: CoreAnalytics { + public init() { } + + + public private(set) var trackEventCallCount = 0 + public var trackEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackEventCallCount += 1 + if let trackEventHandler = trackEventHandler { + trackEventHandler(event, parameters) + } + + } + + public private(set) var trackEventBiValueCallCount = 0 + public var trackEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackEventBiValueCallCount += 1 + if let trackEventBiValueHandler = trackEventBiValueHandler { + trackEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var trackScreenEventCallCount = 0 + public var trackScreenEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackScreenEventCallCount += 1 + if let trackScreenEventHandler = trackScreenEventHandler { + trackScreenEventHandler(event, parameters) + } + + } + + public private(set) var trackScreenEventBiValueCallCount = 0 + public var trackScreenEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackScreenEventBiValueCallCount += 1 + if let trackScreenEventBiValueHandler = trackScreenEventBiValueHandler { + trackScreenEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var appreviewCallCount = 0 + public var appreviewHandler: ((AnalyticsEvent, EventBIValue, String?, Int?) -> ())? + public func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { + appreviewCallCount += 1 + if let appreviewHandler = appreviewHandler { + appreviewHandler(event, biValue, action, rating) + } + + } + + public private(set) var videoQualityChangedCallCount = 0 + public var videoQualityChangedHandler: ((AnalyticsEvent, EventBIValue, String, String) -> ())? + public func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { + videoQualityChangedCallCount += 1 + if let videoQualityChangedHandler = videoQualityChangedHandler { + videoQualityChangedHandler(event, bivalue, value, oldValue) + } + + } +} + +public final class CoreStorageMock: CoreStorage, @unchecked Sendable { + public init() { } + public init(accessToken: String? = nil, refreshToken: String? = nil, pushToken: String? = nil, appleSignFullName: String? = nil, appleSignEmail: String? = nil, cookiesDate: Date? = nil, reviewLastShownVersion: String? = nil, lastReviewDate: Date? = nil, user: DataLayer.User? = nil, userSettings: UserSettings? = nil, resetAppSupportDirectoryUserData: Bool? = nil, useRelativeDates: Bool = false, lastUsedSocialAuth: String? = nil, latestAvailableAppVersion: String? = nil, updateAppRequired: Bool = false) { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.pushToken = pushToken + self.appleSignFullName = appleSignFullName + self.appleSignEmail = appleSignEmail + self.cookiesDate = cookiesDate + self.reviewLastShownVersion = reviewLastShownVersion + self.lastReviewDate = lastReviewDate + self.user = user + self.userSettings = userSettings + self.resetAppSupportDirectoryUserData = resetAppSupportDirectoryUserData + self.useRelativeDates = useRelativeDates + self.lastUsedSocialAuth = lastUsedSocialAuth + self.latestAvailableAppVersion = latestAvailableAppVersion + self.updateAppRequired = updateAppRequired + } + + + public private(set) var accessTokenSetCallCount = 0 + public var accessToken: String? = nil { didSet { accessTokenSetCallCount += 1 } } + + public private(set) var refreshTokenSetCallCount = 0 + public var refreshToken: String? = nil { didSet { refreshTokenSetCallCount += 1 } } + + public private(set) var pushTokenSetCallCount = 0 + public var pushToken: String? = nil { didSet { pushTokenSetCallCount += 1 } } + + public private(set) var appleSignFullNameSetCallCount = 0 + public var appleSignFullName: String? = nil { didSet { appleSignFullNameSetCallCount += 1 } } + + public private(set) var appleSignEmailSetCallCount = 0 + public var appleSignEmail: String? = nil { didSet { appleSignEmailSetCallCount += 1 } } + + public private(set) var cookiesDateSetCallCount = 0 + public var cookiesDate: Date? = nil { didSet { cookiesDateSetCallCount += 1 } } + + public private(set) var reviewLastShownVersionSetCallCount = 0 + public var reviewLastShownVersion: String? = nil { didSet { reviewLastShownVersionSetCallCount += 1 } } + + public private(set) var lastReviewDateSetCallCount = 0 + public var lastReviewDate: Date? = nil { didSet { lastReviewDateSetCallCount += 1 } } + + public private(set) var userSetCallCount = 0 + public var user: DataLayer.User? = nil { didSet { userSetCallCount += 1 } } + + public private(set) var userSettingsSetCallCount = 0 + public var userSettings: UserSettings? = nil { didSet { userSettingsSetCallCount += 1 } } + + public private(set) var resetAppSupportDirectoryUserDataSetCallCount = 0 + public var resetAppSupportDirectoryUserData: Bool? = nil { didSet { resetAppSupportDirectoryUserDataSetCallCount += 1 } } + + public private(set) var useRelativeDatesSetCallCount = 0 + public var useRelativeDates: Bool = false { didSet { useRelativeDatesSetCallCount += 1 } } + + public private(set) var lastUsedSocialAuthSetCallCount = 0 + public var lastUsedSocialAuth: String? = nil { didSet { lastUsedSocialAuthSetCallCount += 1 } } + + public private(set) var latestAvailableAppVersionSetCallCount = 0 + public var latestAvailableAppVersion: String? = nil { didSet { latestAvailableAppVersionSetCallCount += 1 } } + + public private(set) var updateAppRequiredSetCallCount = 0 + public var updateAppRequired: Bool = false { didSet { updateAppRequiredSetCallCount += 1 } } + + private let clearState = MockoloMutex(MockoloHandlerState ()>()) + public var clearCallCount: Int { + return clearState.withLock(\.callCount) + } + public var clearHandler: (@Sendable () -> ())? { + get { clearState.withLock(\.handler) } + set { clearState.withLock { $0.handler = newValue } } + } + public func clear() { + let clearHandler = clearState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearHandler = clearHandler { + clearHandler() + } + + } +} + +public final class AuthInteractorProtocolMock: AuthInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let loginState = MockoloMutex(MockoloHandlerState User>()) + public var loginCallCount: Int { + return loginState.withLock(\.callCount) + } + public var loginHandler: (@Sendable (String, String) async throws -> User)? { + get { loginState.withLock(\.handler) } + set { loginState.withLock { $0.handler = newValue } } + } + public func login(username: String, password: String) async throws -> User { + let loginHandler = loginState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginHandler = loginHandler { + return try await loginHandler(username, password) + } + fatalError("loginHandler returns can't have a default value thus its handler must be set") + } + + private let loginExternalTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginExternalTokenCallCount: Int { + return loginExternalTokenState.withLock(\.callCount) + } + public var loginExternalTokenHandler: (@Sendable (String, String) async throws -> User)? { + get { loginExternalTokenState.withLock(\.handler) } + set { loginExternalTokenState.withLock { $0.handler = newValue } } + } + public func login(externalToken: String, backend: String) async throws -> User { + let loginExternalTokenHandler = loginExternalTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginExternalTokenHandler = loginExternalTokenHandler { + return try await loginExternalTokenHandler(externalToken, backend) + } + fatalError("loginExternalTokenHandler returns can't have a default value thus its handler must be set") + } + + private let loginSsoTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginSsoTokenCallCount: Int { + return loginSsoTokenState.withLock(\.callCount) + } + public var loginSsoTokenHandler: (@Sendable (String) async throws -> User)? { + get { loginSsoTokenState.withLock(\.handler) } + set { loginSsoTokenState.withLock { $0.handler = newValue } } + } + public func login(ssoToken: String) async throws -> User { + let loginSsoTokenHandler = loginSsoTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginSsoTokenHandler = loginSsoTokenHandler { + return try await loginSsoTokenHandler(ssoToken) + } + fatalError("loginSsoTokenHandler returns can't have a default value thus its handler must be set") + } + + private let resetPasswordState = MockoloMutex(MockoloHandlerState ResetPassword>()) + public var resetPasswordCallCount: Int { + return resetPasswordState.withLock(\.callCount) + } + public var resetPasswordHandler: (@Sendable (String) async throws -> ResetPassword)? { + get { resetPasswordState.withLock(\.handler) } + set { resetPasswordState.withLock { $0.handler = newValue } } + } + public func resetPassword(email: String) async throws -> ResetPassword { + let resetPasswordHandler = resetPasswordState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resetPasswordHandler = resetPasswordHandler { + return try await resetPasswordHandler(email) + } + fatalError("resetPasswordHandler returns can't have a default value thus its handler must be set") + } + + private let getCookiesState = MockoloMutex(MockoloHandlerState ()>()) + public var getCookiesCallCount: Int { + return getCookiesState.withLock(\.callCount) + } + public var getCookiesHandler: (@Sendable (Bool) async throws -> ())? { + get { getCookiesState.withLock(\.handler) } + set { getCookiesState.withLock { $0.handler = newValue } } + } + public func getCookies(force: Bool) async throws { + let getCookiesHandler = getCookiesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCookiesHandler = getCookiesHandler { + try await getCookiesHandler(force) + } + + } + + private let getRegistrationFieldsState = MockoloMutex(MockoloHandlerState [PickerFields]>()) + public var getRegistrationFieldsCallCount: Int { + return getRegistrationFieldsState.withLock(\.callCount) + } + public var getRegistrationFieldsHandler: (@Sendable () async throws -> [PickerFields])? { + get { getRegistrationFieldsState.withLock(\.handler) } + set { getRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func getRegistrationFields() async throws -> [PickerFields] { + let getRegistrationFieldsHandler = getRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getRegistrationFieldsHandler = getRegistrationFieldsHandler { + return try await getRegistrationFieldsHandler() + } + return [PickerFields]() + } + + private let registerUserState = MockoloMutex(MockoloHandlerState User>()) + public var registerUserCallCount: Int { + return registerUserState.withLock(\.callCount) + } + public var registerUserHandler: (@Sendable ([String: String], Bool) async throws -> User)? { + get { registerUserState.withLock(\.handler) } + set { registerUserState.withLock { $0.handler = newValue } } + } + public func registerUser(fields: [String: String], isSocial: Bool) async throws -> User { + let registerUserHandler = registerUserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let registerUserHandler = registerUserHandler { + return try await registerUserHandler(fields, isSocial) + } + fatalError("registerUserHandler returns can't have a default value thus its handler must be set") + } + + private let validateRegistrationFieldsState = MockoloMutex(MockoloHandlerState [String: String]>()) + public var validateRegistrationFieldsCallCount: Int { + return validateRegistrationFieldsState.withLock(\.callCount) + } + public var validateRegistrationFieldsHandler: (@Sendable ([String: String]) async throws -> [String: String])? { + get { validateRegistrationFieldsState.withLock(\.handler) } + set { validateRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func validateRegistrationFields(fields: [String: String]) async throws -> [String: String] { + let validateRegistrationFieldsHandler = validateRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let validateRegistrationFieldsHandler = validateRegistrationFieldsHandler { + return try await validateRegistrationFieldsHandler(fields) + } + return [String: String]() + } +} + +public final class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let submitOfflineProgressState = MockoloMutex(MockoloHandlerState Bool>()) + public var submitOfflineProgressCallCount: Int { + return submitOfflineProgressState.withLock(\.callCount) + } + public var submitOfflineProgressHandler: (@Sendable (String, String, String) async throws -> Bool)? { + get { submitOfflineProgressState.withLock(\.handler) } + set { submitOfflineProgressState.withLock { $0.handler = newValue } } + } + public func submitOfflineProgress(courseID: String, blockID: String, data: String) async throws -> Bool { + let submitOfflineProgressHandler = submitOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let submitOfflineProgressHandler = submitOfflineProgressHandler { + return try await submitOfflineProgressHandler(courseID, blockID, data) + } + return false + } +} + +public final class WebviewCookiesUpdateProtocolMock: WebviewCookiesUpdateProtocol { + public init() { } + public init(authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock(), cookiesReady: Bool = false, updatingCookies: Bool = false, errorMessage: String? = nil) { + self.authInteractor = authInteractor + self.cookiesReady = cookiesReady + self.updatingCookies = updatingCookies + self.errorMessage = errorMessage + } + + + + public var authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock() + + public private(set) var cookiesReadySetCallCount = 0 + public var cookiesReady: Bool = false { didSet { cookiesReadySetCallCount += 1 } } + + public private(set) var updatingCookiesSetCallCount = 0 + public var updatingCookies: Bool = false { didSet { updatingCookiesSetCallCount += 1 } } + + public private(set) var errorMessageSetCallCount = 0 + public var errorMessage: String? = nil { didSet { errorMessageSetCallCount += 1 } } + + public private(set) var updateCookiesCallCount = 0 + public var updateCookiesHandler: ((Bool, Int) async -> ())? + public func updateCookies(force: Bool, retryCount: Int) async { + updateCookiesCallCount += 1 + if let updateCookiesHandler = updateCookiesHandler { + await updateCookiesHandler(force, retryCount) + } + + } +} + +public final class BaseRouterMock: BaseRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class CalendarManagerProtocolMock: CalendarManagerProtocol, @unchecked Sendable { + public init() { } + + + private let createCalendarIfNeededState = MockoloMutex(MockoloHandlerState ()>()) + public var createCalendarIfNeededCallCount: Int { + return createCalendarIfNeededState.withLock(\.callCount) + } + public var createCalendarIfNeededHandler: (@Sendable () -> ())? { + get { createCalendarIfNeededState.withLock(\.handler) } + set { createCalendarIfNeededState.withLock { $0.handler = newValue } } + } + public func createCalendarIfNeeded() { + let createCalendarIfNeededHandler = createCalendarIfNeededState.withLock { state in + state.callCount += 1 + return state.handler + } + if let createCalendarIfNeededHandler = createCalendarIfNeededHandler { + createCalendarIfNeededHandler() + } + + } + + private let filterCoursesBySelectedState = MockoloMutex(MockoloHandlerState [CourseForSync]>()) + public var filterCoursesBySelectedCallCount: Int { + return filterCoursesBySelectedState.withLock(\.callCount) + } + public var filterCoursesBySelectedHandler: (@Sendable ([CourseForSync]) async -> [CourseForSync])? { + get { filterCoursesBySelectedState.withLock(\.handler) } + set { filterCoursesBySelectedState.withLock { $0.handler = newValue } } + } + public func filterCoursesBySelected(fetchedCourses: [CourseForSync]) async -> [CourseForSync] { + let filterCoursesBySelectedHandler = filterCoursesBySelectedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let filterCoursesBySelectedHandler = filterCoursesBySelectedHandler { + return await filterCoursesBySelectedHandler(fetchedCourses) + } + return [CourseForSync]() + } + + private let removeOldCalendarState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOldCalendarCallCount: Int { + return removeOldCalendarState.withLock(\.callCount) + } + public var removeOldCalendarHandler: (@Sendable () -> ())? { + get { removeOldCalendarState.withLock(\.handler) } + set { removeOldCalendarState.withLock { $0.handler = newValue } } + } + public func removeOldCalendar() { + let removeOldCalendarHandler = removeOldCalendarState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOldCalendarHandler = removeOldCalendarHandler { + removeOldCalendarHandler() + } + + } + + private let removeOutdatedEventsState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOutdatedEventsCallCount: Int { + return removeOutdatedEventsState.withLock(\.callCount) + } + public var removeOutdatedEventsHandler: (@Sendable (String) async -> ())? { + get { removeOutdatedEventsState.withLock(\.handler) } + set { removeOutdatedEventsState.withLock { $0.handler = newValue } } + } + public func removeOutdatedEvents(courseID: String) async { + let removeOutdatedEventsHandler = removeOutdatedEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOutdatedEventsHandler = removeOutdatedEventsHandler { + await removeOutdatedEventsHandler(courseID) + } + + } + + private let syncCourseState = MockoloMutex(MockoloHandlerState ()>()) + public var syncCourseCallCount: Int { + return syncCourseState.withLock(\.callCount) + } + public var syncCourseHandler: (@Sendable (String, String, CourseDates) async -> ())? { + get { syncCourseState.withLock(\.handler) } + set { syncCourseState.withLock { $0.handler = newValue } } + } + public func syncCourse(courseID: String, courseName: String, dates: CourseDates) async { + let syncCourseHandler = syncCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let syncCourseHandler = syncCourseHandler { + await syncCourseHandler(courseID, courseName, dates) + } + + } + + private let requestAccessState = MockoloMutex(MockoloHandlerState Bool>()) + public var requestAccessCallCount: Int { + return requestAccessState.withLock(\.callCount) + } + public var requestAccessHandler: (@Sendable () async -> Bool)? { + get { requestAccessState.withLock(\.handler) } + set { requestAccessState.withLock { $0.handler = newValue } } + } + public func requestAccess() async -> Bool { + let requestAccessHandler = requestAccessState.withLock { state in + state.callCount += 1 + return state.handler + } + if let requestAccessHandler = requestAccessHandler { + return await requestAccessHandler() + } + return false + } + + private let courseStatusState = MockoloMutex(MockoloHandlerState SyncStatus>()) + public var courseStatusCallCount: Int { + return courseStatusState.withLock(\.callCount) + } + public var courseStatusHandler: (@Sendable (String) async -> SyncStatus)? { + get { courseStatusState.withLock(\.handler) } + set { courseStatusState.withLock { $0.handler = newValue } } + } + public func courseStatus(courseID: String) async -> SyncStatus { + let courseStatusHandler = courseStatusState.withLock { state in + state.callCount += 1 + return state.handler + } + if let courseStatusHandler = courseStatusHandler { + return await courseStatusHandler(courseID) + } + fatalError("courseStatusHandler returns can't have a default value thus its handler must be set") + } + + private let clearAllDataState = MockoloMutex(MockoloHandlerState ()>()) + public var clearAllDataCallCount: Int { + return clearAllDataState.withLock(\.callCount) + } + public var clearAllDataHandler: (@Sendable (Bool) async -> ())? { + get { clearAllDataState.withLock(\.handler) } + set { clearAllDataState.withLock { $0.handler = newValue } } + } + public func clearAllData(removeCalendar: Bool) async { + let clearAllDataHandler = clearAllDataState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearAllDataHandler = clearAllDataHandler { + await clearAllDataHandler(removeCalendar) + } + + } + + private let isDatesChangedState = MockoloMutex(MockoloHandlerState Bool>()) + public var isDatesChangedCallCount: Int { + return isDatesChangedState.withLock(\.callCount) + } + public var isDatesChangedHandler: (@Sendable (String, String) async -> Bool)? { + get { isDatesChangedState.withLock(\.handler) } + set { isDatesChangedState.withLock { $0.handler = newValue } } + } + public func isDatesChanged(courseID: String, checksum: String) async -> Bool { + let isDatesChangedHandler = isDatesChangedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isDatesChangedHandler = isDatesChangedHandler { + return await isDatesChangedHandler(courseID, checksum) + } + return false + } +} + +public final class CorePersistenceProtocolMock: CorePersistenceProtocol, @unchecked Sendable { + public init() { } + + + private let setState = MockoloMutex(MockoloHandlerState ()>()) + public var setCallCount: Int { + return setState.withLock(\.callCount) + } + public var setHandler: (@Sendable (Int) -> ())? { + get { setState.withLock(\.handler) } + set { setState.withLock { $0.handler = newValue } } + } + public func set(userId: Int) { + let setHandler = setState.withLock { state in + state.callCount += 1 + return state.handler + } + if let setHandler = setHandler { + setHandler(userId) + } + + } + + private let getUserIDState = MockoloMutex(MockoloHandlerState Int?>()) + public var getUserIDCallCount: Int { + return getUserIDState.withLock(\.callCount) + } + public var getUserIDHandler: (@Sendable () -> Int?)? { + get { getUserIDState.withLock(\.handler) } + set { getUserIDState.withLock { $0.handler = newValue } } + } + public func getUserID() -> Int? { + let getUserIDHandler = getUserIDState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getUserIDHandler = getUserIDHandler { + return getUserIDHandler() + } + return nil + } + + private let publisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var publisherCallCount: Int { + return publisherState.withLock(\.callCount) + } + public var publisherHandler: (@Sendable () throws -> AnyPublisher)? { + get { publisherState.withLock(\.handler) } + set { publisherState.withLock { $0.handler = newValue } } + } + public func publisher() throws -> AnyPublisher { + let publisherHandler = publisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let publisherHandler = publisherHandler { + return try publisherHandler() + } + fatalError("publisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([DownloadDataTask]) -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(tasks: [DownloadDataTask]) { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + addToDownloadQueueHandler(tasks) + } + + } + + private let saveOfflineProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var saveOfflineProgressCallCount: Int { + return saveOfflineProgressState.withLock(\.callCount) + } + public var saveOfflineProgressHandler: (@Sendable (OfflineProgress) async -> ())? { + get { saveOfflineProgressState.withLock(\.handler) } + set { saveOfflineProgressState.withLock { $0.handler = newValue } } + } + public func saveOfflineProgress(progress: OfflineProgress) async { + let saveOfflineProgressHandler = saveOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveOfflineProgressHandler = saveOfflineProgressHandler { + await saveOfflineProgressHandler(progress) + } + + } + + private let loadProgressState = MockoloMutex(MockoloHandlerState OfflineProgress?>()) + public var loadProgressCallCount: Int { + return loadProgressState.withLock(\.callCount) + } + public var loadProgressHandler: (@Sendable (String) async -> OfflineProgress?)? { + get { loadProgressState.withLock(\.handler) } + set { loadProgressState.withLock { $0.handler = newValue } } + } + public func loadProgress(for blockID: String) async -> OfflineProgress? { + let loadProgressHandler = loadProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadProgressHandler = loadProgressHandler { + return await loadProgressHandler(blockID) + } + return nil + } + + private let loadAllOfflineProgressState = MockoloMutex(MockoloHandlerState [OfflineProgress]>()) + public var loadAllOfflineProgressCallCount: Int { + return loadAllOfflineProgressState.withLock(\.callCount) + } + public var loadAllOfflineProgressHandler: (@Sendable () async -> [OfflineProgress])? { + get { loadAllOfflineProgressState.withLock(\.handler) } + set { loadAllOfflineProgressState.withLock { $0.handler = newValue } } + } + public func loadAllOfflineProgress() async -> [OfflineProgress] { + let loadAllOfflineProgressHandler = loadAllOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadAllOfflineProgressHandler = loadAllOfflineProgressHandler { + return await loadAllOfflineProgressHandler() + } + return [OfflineProgress]() + } + + private let deleteProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteProgressCallCount: Int { + return deleteProgressState.withLock(\.callCount) + } + public var deleteProgressHandler: (@Sendable (String) async -> ())? { + get { deleteProgressState.withLock(\.handler) } + set { deleteProgressState.withLock { $0.handler = newValue } } + } + public func deleteProgress(for blockID: String) async { + let deleteProgressHandler = deleteProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteProgressHandler = deleteProgressHandler { + await deleteProgressHandler(blockID) + } + + } + + private let deleteAllProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllProgressCallCount: Int { + return deleteAllProgressState.withLock(\.callCount) + } + public var deleteAllProgressHandler: (@Sendable () async -> ())? { + get { deleteAllProgressState.withLock(\.handler) } + set { deleteAllProgressState.withLock { $0.handler = newValue } } + } + public func deleteAllProgress() async { + let deleteAllProgressHandler = deleteAllProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllProgressHandler = deleteAllProgressHandler { + await deleteAllProgressHandler() + } + + } + + private let addToDownloadQueueBlocksState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueBlocksCallCount: Int { + return addToDownloadQueueBlocksState.withLock(\.callCount) + } + public var addToDownloadQueueBlocksHandler: (@Sendable ([CourseBlock], DownloadQuality) -> ())? { + get { addToDownloadQueueBlocksState.withLock(\.handler) } + set { addToDownloadQueueBlocksState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { + let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksHandler { + addToDownloadQueueBlocksHandler(blocks, downloadQuality) + } + + } + + private let updateTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var updateTaskCallCount: Int { + return updateTaskState.withLock(\.callCount) + } + public var updateTaskHandler: (@Sendable (DownloadDataTask) -> ())? { + get { updateTaskState.withLock(\.handler) } + set { updateTaskState.withLock { $0.handler = newValue } } + } + public func updateTask(task: DownloadDataTask) { + let updateTaskHandler = updateTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateTaskHandler = updateTaskHandler { + updateTaskHandler(task) + } + + } + + private let downloadDataTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadDataTaskCallCount: Int { + return downloadDataTaskState.withLock(\.callCount) + } + public var downloadDataTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadDataTaskState.withLock(\.handler) } + set { downloadDataTaskState.withLock { $0.handler = newValue } } + } + public func downloadDataTask(for blockId: String) async -> DownloadDataTask? { + let downloadDataTaskHandler = downloadDataTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadDataTaskHandler = downloadDataTaskHandler { + return await downloadDataTaskHandler(blockId) + } + return nil + } + + private let getDownloadDataTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksCallCount: Int { + return getDownloadDataTasksState.withLock(\.callCount) + } + public var getDownloadDataTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadDataTasksState.withLock(\.handler) } + set { getDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasks() async -> [DownloadDataTask] { + let getDownloadDataTasksHandler = getDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksHandler = getDownloadDataTasksHandler { + return await getDownloadDataTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadDataTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksForCourseCallCount: Int { + return getDownloadDataTasksForCourseState.withLock(\.callCount) + } + public var getDownloadDataTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadDataTasksForCourseState.withLock(\.handler) } + set { getDownloadDataTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseHandler { + return await getDownloadDataTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let deleteDownloadDataTasksState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteDownloadDataTasksCallCount: Int { + return deleteDownloadDataTasksState.withLock(\.callCount) + } + public var deleteDownloadDataTasksHandler: (@Sendable ([String]) -> ())? { + get { deleteDownloadDataTasksState.withLock(\.handler) } + set { deleteDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func deleteDownloadDataTasks(ids: [String]) { + let deleteDownloadDataTasksHandler = deleteDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteDownloadDataTasksHandler = deleteDownloadDataTasksHandler { + deleteDownloadDataTasksHandler(ids) + } + + } +} + +public final class DownloadsAnalyticsMock: DownloadsAnalytics { + public init() { } + + + public private(set) var downloadCourseClickedCallCount = 0 + public var downloadCourseClickedHandler: ((String, String) -> ())? + public func downloadCourseClicked(courseId: String, courseName: String) { + downloadCourseClickedCallCount += 1 + if let downloadCourseClickedHandler = downloadCourseClickedHandler { + downloadCourseClickedHandler(courseId, courseName) + } + + } + + public private(set) var cancelDownloadClickedCallCount = 0 + public var cancelDownloadClickedHandler: ((String, String) -> ())? + public func cancelDownloadClicked(courseId: String, courseName: String) { + cancelDownloadClickedCallCount += 1 + if let cancelDownloadClickedHandler = cancelDownloadClickedHandler { + cancelDownloadClickedHandler(courseId, courseName) + } + + } + + public private(set) var removeDownloadClickedCallCount = 0 + public var removeDownloadClickedHandler: ((String, String) -> ())? + public func removeDownloadClicked(courseId: String, courseName: String) { + removeDownloadClickedCallCount += 1 + if let removeDownloadClickedHandler = removeDownloadClickedHandler { + removeDownloadClickedHandler(courseId, courseName) + } + + } + + public private(set) var downloadConfirmedCallCount = 0 + public var downloadConfirmedHandler: ((String, String, Int64) -> ())? + public func downloadConfirmed(courseId: String, courseName: String, downloadSize: Int64) { + downloadConfirmedCallCount += 1 + if let downloadConfirmedHandler = downloadConfirmedHandler { + downloadConfirmedHandler(courseId, courseName, downloadSize) + } + + } + + public private(set) var downloadCancelledCallCount = 0 + public var downloadCancelledHandler: ((String, String) -> ())? + public func downloadCancelled(courseId: String, courseName: String) { + downloadCancelledCallCount += 1 + if let downloadCancelledHandler = downloadCancelledHandler { + downloadCancelledHandler(courseId, courseName) + } + + } + + public private(set) var downloadRemovedCallCount = 0 + public var downloadRemovedHandler: ((String, String, Int64) -> ())? + public func downloadRemoved(courseId: String, courseName: String, downloadSize: Int64) { + downloadRemovedCallCount += 1 + if let downloadRemovedHandler = downloadRemovedHandler { + downloadRemovedHandler(courseId, courseName, downloadSize) + } + + } + + public private(set) var downloadErrorCallCount = 0 + public var downloadErrorHandler: ((String, String, String) -> ())? + public func downloadError(courseId: String, courseName: String, errorType: String) { + downloadErrorCallCount += 1 + if let downloadErrorHandler = downloadErrorHandler { + downloadErrorHandler(courseId, courseName, errorType) + } + + } + + public private(set) var downloadCompletedCallCount = 0 + public var downloadCompletedHandler: ((String, String, Int64) -> ())? + public func downloadCompleted(courseId: String, courseName: String, downloadSize: Int64) { + downloadCompletedCallCount += 1 + if let downloadCompletedHandler = downloadCompletedHandler { + downloadCompletedHandler(courseId, courseName, downloadSize) + } + + } + + public private(set) var downloadStartedCallCount = 0 + public var downloadStartedHandler: ((String, String, Int64) -> ())? + public func downloadStarted(courseId: String, courseName: String, downloadSize: Int64) { + downloadStartedCallCount += 1 + if let downloadStartedHandler = downloadStartedHandler { + downloadStartedHandler(courseId, courseName, downloadSize) + } + + } + + public private(set) var downloadsScreenViewedCallCount = 0 + public var downloadsScreenViewedHandler: (() -> ())? + public func downloadsScreenViewed() { + downloadsScreenViewedCallCount += 1 + if let downloadsScreenViewedHandler = downloadsScreenViewedHandler { + downloadsScreenViewedHandler() + } + + } +} + +public final class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseBlocksCallCount: Int { + return getCourseBlocksState.withLock(\.callCount) + } + public var getCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getCourseBlocksState.withLock(\.handler) } + set { getCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseBlocks(courseID: String) async throws -> CourseStructure { + let getCourseBlocksHandler = getCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseBlocksHandler = getCourseBlocksHandler { + return try await getCourseBlocksHandler(courseID) + } + fatalError("getCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getLoadedCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getLoadedCourseBlocksCallCount: Int { + return getLoadedCourseBlocksState.withLock(\.callCount) + } + public var getLoadedCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getLoadedCourseBlocksState.withLock(\.handler) } + set { getLoadedCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure { + let getLoadedCourseBlocksHandler = getLoadedCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseBlocksHandler = getLoadedCourseBlocksHandler { + return try await getLoadedCourseBlocksHandler(courseID) + } + fatalError("getLoadedCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let shiftDueDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var shiftDueDatesCallCount: Int { + return shiftDueDatesState.withLock(\.callCount) + } + public var shiftDueDatesHandler: (@Sendable (String) async throws -> ())? { + get { shiftDueDatesState.withLock(\.handler) } + set { shiftDueDatesState.withLock { $0.handler = newValue } } + } + public func shiftDueDates(courseID: String) async throws { + let shiftDueDatesHandler = shiftDueDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let shiftDueDatesHandler = shiftDueDatesHandler { + try await shiftDueDatesHandler(courseID) + } + + } +} + +public final class DownloadsInteractorProtocolMock: DownloadsInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let getDownloadCoursesState = MockoloMutex(MockoloHandlerState [DownloadCoursePreview]>()) + public var getDownloadCoursesCallCount: Int { + return getDownloadCoursesState.withLock(\.callCount) + } + public var getDownloadCoursesHandler: (@Sendable () async throws -> [DownloadCoursePreview])? { + get { getDownloadCoursesState.withLock(\.handler) } + set { getDownloadCoursesState.withLock { $0.handler = newValue } } + } + public func getDownloadCourses() async throws -> [DownloadCoursePreview] { + let getDownloadCoursesHandler = getDownloadCoursesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadCoursesHandler = getDownloadCoursesHandler { + return try await getDownloadCoursesHandler() + } + return [DownloadCoursePreview]() + } + + private let getDownloadCoursesOfflineState = MockoloMutex(MockoloHandlerState [DownloadCoursePreview]>()) + public var getDownloadCoursesOfflineCallCount: Int { + return getDownloadCoursesOfflineState.withLock(\.callCount) + } + public var getDownloadCoursesOfflineHandler: (@Sendable () async throws -> [DownloadCoursePreview])? { + get { getDownloadCoursesOfflineState.withLock(\.handler) } + set { getDownloadCoursesOfflineState.withLock { $0.handler = newValue } } + } + public func getDownloadCoursesOffline() async throws -> [DownloadCoursePreview] { + let getDownloadCoursesOfflineHandler = getDownloadCoursesOfflineState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadCoursesOfflineHandler = getDownloadCoursesOfflineHandler { + return try await getDownloadCoursesOfflineHandler() + } + return [DownloadCoursePreview]() + } +} + +public final class DownloadsHelperProtocolMock: DownloadsHelperProtocol, @unchecked Sendable { + public init() { } + + + private let calculateDownloadProgressState = MockoloMutex(MockoloHandlerState (downloaded: Int, total: Int)>()) + public var calculateDownloadProgressCallCount: Int { + return calculateDownloadProgressState.withLock(\.callCount) + } + public var calculateDownloadProgressHandler: (@Sendable (String) async -> (downloaded: Int, total: Int))? { + get { calculateDownloadProgressState.withLock(\.handler) } + set { calculateDownloadProgressState.withLock { $0.handler = newValue } } + } + public func calculateDownloadProgress(courseID: String) async -> (downloaded: Int, total: Int) { + let calculateDownloadProgressHandler = calculateDownloadProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let calculateDownloadProgressHandler = calculateDownloadProgressHandler { + return await calculateDownloadProgressHandler(courseID) + } + return (0, 0) + } + + private let isDownloadingState = MockoloMutex(MockoloHandlerState Bool>()) + public var isDownloadingCallCount: Int { + return isDownloadingState.withLock(\.callCount) + } + public var isDownloadingHandler: (@Sendable (String) async -> Bool)? { + get { isDownloadingState.withLock(\.handler) } + set { isDownloadingState.withLock { $0.handler = newValue } } + } + public func isDownloading(courseID: String) async -> Bool { + let isDownloadingHandler = isDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isDownloadingHandler = isDownloadingHandler { + return await isDownloadingHandler(courseID) + } + return false + } + + private let isFullyDownloadedState = MockoloMutex(MockoloHandlerState Bool>()) + public var isFullyDownloadedCallCount: Int { + return isFullyDownloadedState.withLock(\.callCount) + } + public var isFullyDownloadedHandler: (@Sendable (String) async -> Bool)? { + get { isFullyDownloadedState.withLock(\.handler) } + set { isFullyDownloadedState.withLock { $0.handler = newValue } } + } + public func isFullyDownloaded(courseID: String) async -> Bool { + let isFullyDownloadedHandler = isFullyDownloadedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isFullyDownloadedHandler = isFullyDownloadedHandler { + return await isFullyDownloadedHandler(courseID) + } + return false + } + + private let getDownloadTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksForCourseCallCount: Int { + return getDownloadTasksForCourseState.withLock(\.callCount) + } + public var getDownloadTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadTasksForCourseState.withLock(\.handler) } + set { getDownloadTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadTasksForCourse(courseID: String) async -> [DownloadDataTask] { + let getDownloadTasksForCourseHandler = getDownloadTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksForCourseHandler = getDownloadTasksForCourseHandler { + return await getDownloadTasksForCourseHandler(courseID) + } + return [DownloadDataTask]() + } +} + +public final class ConnectivityProtocolMock: ConnectivityProtocol, @unchecked Sendable { + public init() { } + public init(isInternetAvaliable: Bool = false, isMobileData: Bool = false) { + self.isInternetAvaliable = isInternetAvaliable + self.isMobileData = isMobileData + } + + + + public var isInternetAvaliable: Bool = false + + + public var isMobileData: Bool = false + + + private var _internetReachableSubject: CurrentValueSubject! + public var internetReachableSubject: CurrentValueSubject { + get { return _internetReachableSubject } + set { _internetReachableSubject = newValue } + } +} + +public final class DownloadManagerProtocolMock: DownloadManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCurrentDownloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var getCurrentDownloadTaskCallCount: Int { + return getCurrentDownloadTaskState.withLock(\.callCount) + } + public var getCurrentDownloadTaskHandler: (@Sendable () async -> DownloadDataTask?)? { + get { getCurrentDownloadTaskState.withLock(\.handler) } + set { getCurrentDownloadTaskState.withLock { $0.handler = newValue } } + } + public func getCurrentDownloadTask() async -> DownloadDataTask? { + let getCurrentDownloadTaskHandler = getCurrentDownloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCurrentDownloadTaskHandler = getCurrentDownloadTaskHandler { + return await getCurrentDownloadTaskHandler() + } + return nil + } + + private let eventPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var eventPublisherCallCount: Int { + return eventPublisherState.withLock(\.callCount) + } + public var eventPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { eventPublisherState.withLock(\.handler) } + set { eventPublisherState.withLock { $0.handler = newValue } } + } + public func eventPublisher() -> AnyPublisher { + let eventPublisherHandler = eventPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let eventPublisherHandler = eventPublisherHandler { + return eventPublisherHandler() + } + fatalError("eventPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([CourseBlock]) async throws -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock]) async throws { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + try await addToDownloadQueueHandler(blocks) + } + + } + + private let getDownloadTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksCallCount: Int { + return getDownloadTasksState.withLock(\.callCount) + } + public var getDownloadTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadTasksState.withLock(\.handler) } + set { getDownloadTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadTasks() async -> [DownloadDataTask] { + let getDownloadTasksHandler = getDownloadTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksHandler = getDownloadTasksHandler { + return await getDownloadTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksForCourseCallCount: Int { + return getDownloadTasksForCourseState.withLock(\.callCount) + } + public var getDownloadTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadTasksForCourseState.withLock(\.handler) } + set { getDownloadTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadTasksForCourseHandler = getDownloadTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksForCourseHandler = getDownloadTasksForCourseHandler { + return await getDownloadTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let cancelDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCallCount: Int { + return cancelDownloadingState.withLock(\.callCount) + } + public var cancelDownloadingHandler: (@Sendable (String, [CourseBlock]) async throws -> ())? { + get { cancelDownloadingState.withLock(\.handler) } + set { cancelDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String, blocks: [CourseBlock]) async throws { + let cancelDownloadingHandler = cancelDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingHandler = cancelDownloadingHandler { + try await cancelDownloadingHandler(courseId, blocks) + } + + } + + private let cancelDownloadingTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingTaskCallCount: Int { + return cancelDownloadingTaskState.withLock(\.callCount) + } + public var cancelDownloadingTaskHandler: (@Sendable (DownloadDataTask) async throws -> ())? { + get { cancelDownloadingTaskState.withLock(\.handler) } + set { cancelDownloadingTaskState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(task: DownloadDataTask) async throws { + let cancelDownloadingTaskHandler = cancelDownloadingTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingTaskHandler = cancelDownloadingTaskHandler { + try await cancelDownloadingTaskHandler(task) + } + + } + + private let cancelDownloadingCourseIdState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCourseIdCallCount: Int { + return cancelDownloadingCourseIdState.withLock(\.callCount) + } + public var cancelDownloadingCourseIdHandler: (@Sendable (String) async throws -> ())? { + get { cancelDownloadingCourseIdState.withLock(\.handler) } + set { cancelDownloadingCourseIdState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String) async throws { + let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdHandler { + try await cancelDownloadingCourseIdHandler(courseId) + } + + } + + private let cancelAllDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelAllDownloadingCallCount: Int { + return cancelAllDownloadingState.withLock(\.callCount) + } + public var cancelAllDownloadingHandler: (@Sendable () async throws -> ())? { + get { cancelAllDownloadingState.withLock(\.handler) } + set { cancelAllDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelAllDownloading() async throws { + let cancelAllDownloadingHandler = cancelAllDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelAllDownloadingHandler = cancelAllDownloadingHandler { + try await cancelAllDownloadingHandler() + } + + } + + private let deleteAllState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllCallCount: Int { + return deleteAllState.withLock(\.callCount) + } + public var deleteAllHandler: (@Sendable () async -> ())? { + get { deleteAllState.withLock(\.handler) } + set { deleteAllState.withLock { $0.handler = newValue } } + } + public func deleteAll() async { + let deleteAllHandler = deleteAllState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllHandler = deleteAllHandler { + await deleteAllHandler() + } + + } + + private let fileUrlState = MockoloMutex(MockoloHandlerState URL?>()) + public var fileUrlCallCount: Int { + return fileUrlState.withLock(\.callCount) + } + public var fileUrlHandler: (@Sendable (String) async -> URL?)? { + get { fileUrlState.withLock(\.handler) } + set { fileUrlState.withLock { $0.handler = newValue } } + } + public func fileUrl(for blockId: String) async -> URL? { + let fileUrlHandler = fileUrlState.withLock { state in + state.callCount += 1 + return state.handler + } + if let fileUrlHandler = fileUrlHandler { + return await fileUrlHandler(blockId) + } + return nil + } + + private let resumeDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var resumeDownloadingCallCount: Int { + return resumeDownloadingState.withLock(\.callCount) + } + public var resumeDownloadingHandler: (@Sendable () async throws -> ())? { + get { resumeDownloadingState.withLock(\.handler) } + set { resumeDownloadingState.withLock { $0.handler = newValue } } + } + public func resumeDownloading() async throws { + let resumeDownloadingHandler = resumeDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resumeDownloadingHandler = resumeDownloadingHandler { + try await resumeDownloadingHandler() + } + + } + + private let isLargeVideosSizeState = MockoloMutex(MockoloHandlerState Bool>()) + public var isLargeVideosSizeCallCount: Int { + return isLargeVideosSizeState.withLock(\.callCount) + } + public var isLargeVideosSizeHandler: (@Sendable ([CourseBlock]) async -> Bool)? { + get { isLargeVideosSizeState.withLock(\.handler) } + set { isLargeVideosSizeState.withLock { $0.handler = newValue } } + } + public func isLargeVideosSize(blocks: [CourseBlock]) async -> Bool { + let isLargeVideosSizeHandler = isLargeVideosSizeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isLargeVideosSizeHandler = isLargeVideosSizeHandler { + return await isLargeVideosSizeHandler(blocks) + } + return false + } + + private let removeAppSupportDirectoryUnusedContentState = MockoloMutex(MockoloHandlerState ()>()) + public var removeAppSupportDirectoryUnusedContentCallCount: Int { + return removeAppSupportDirectoryUnusedContentState.withLock(\.callCount) + } + public var removeAppSupportDirectoryUnusedContentHandler: (@Sendable () -> ())? { + get { removeAppSupportDirectoryUnusedContentState.withLock(\.handler) } + set { removeAppSupportDirectoryUnusedContentState.withLock { $0.handler = newValue } } + } + public func removeAppSupportDirectoryUnusedContent() { + let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentHandler { + removeAppSupportDirectoryUnusedContentHandler() + } + + } + + private let deleteState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteCallCount: Int { + return deleteState.withLock(\.callCount) + } + public var deleteHandler: (@Sendable ([CourseBlock], String) async -> ())? { + get { deleteState.withLock(\.handler) } + set { deleteState.withLock { $0.handler = newValue } } + } + public func delete(blocks: [CourseBlock], courseId: String) async { + let deleteHandler = deleteState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteHandler = deleteHandler { + await deleteHandler(blocks, courseId) + } + + } + + private let downloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadTaskCallCount: Int { + return downloadTaskState.withLock(\.callCount) + } + public var downloadTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadTaskState.withLock(\.handler) } + set { downloadTaskState.withLock { $0.handler = newValue } } + } + public func downloadTask(for blockId: String) async -> DownloadDataTask? { + let downloadTaskHandler = downloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadTaskHandler = downloadTaskHandler { + return await downloadTaskHandler(blockId) + } + return nil + } + + private let getFreeDiskSpaceState = MockoloMutex(MockoloHandlerState Int?>()) + public var getFreeDiskSpaceCallCount: Int { + return getFreeDiskSpaceState.withLock(\.callCount) + } + public var getFreeDiskSpaceHandler: (@Sendable () -> Int?)? { + get { getFreeDiskSpaceState.withLock(\.handler) } + set { getFreeDiskSpaceState.withLock { $0.handler = newValue } } + } + public func getFreeDiskSpace() -> Int? { + let getFreeDiskSpaceHandler = getFreeDiskSpaceState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getFreeDiskSpaceHandler = getFreeDiskSpaceHandler { + return getFreeDiskSpaceHandler() + } + return nil + } +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { + print("At \(function), the captured arguments are not Sendable, it is not concurrency-safe.") +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { +} + +/// Will be replaced to `Synchronization.Mutex` in future. +fileprivate final class MockoloMutex: @unchecked Sendable { + private let lock = NSLock() + private var value: Value + init(_ initialValue: Value) { + self.value = initialValue + } +#if compiler(>=6.0) + borrowing func withLock(_ body: (inout sending Value) throws(E) -> Result) throws(E) -> sending Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#else + func withLock(_ body: (inout Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#endif +} + +fileprivate struct MockoloUnsafeTransfer: @unchecked Sendable { + var value: Value + init(_ value: Value) { + self.value = value + } +} + +fileprivate struct MockoloHandlerState { + var argValues: [MockoloUnsafeTransfer] = [] + var handler: Handler? = nil + var callCount: Int = 0 +} + diff --git a/Downloads/Mockfile b/Downloads/Mockfile deleted file mode 100644 index 4550b181c..000000000 --- a/Downloads/Mockfile +++ /dev/null @@ -1,18 +0,0 @@ -sourceryCommand: mint run krzysztofzablocki/Sourcery@2.1.2 sourcery -sourceryTemplate: ../MockTemplate.swifttemplate -unit.tests.mock: - sources: - include: - - ./../Core - - ./Downloads - exclude: [] - output: ./DownloadsTests/Downloads Mock.generated.swift - targets: - - MyAppUnitTests - import: - - Core - - Downloads - - Foundation - - SwiftUI - - Combine - - OEXFoundation \ No newline at end of file diff --git a/MockTemplate.swifttemplate b/MockTemplate.swifttemplate deleted file mode 100644 index 95d0d857a..000000000 --- a/MockTemplate.swifttemplate +++ /dev/null @@ -1,2133 +0,0 @@ -<%_ -let mockTypeName = "Mock" -func swiftLintRules(_ arguments: [String: Any]) -> [String] { - return stringArray(fromArguments: arguments, forKey: "excludedSwiftLintRules").map { rule in - return "//swiftlint:disable \(rule)" - } -} - -func projectImports(_ arguments: [String: Any]) -> [String] { - return imports(arguments) + testableImports(arguments) -} - -func imports(_ arguments: [String: Any]) -> [String] { - return stringArray(fromArguments: arguments, forKey: "import") - .map { return "import \($0)" } -} - -func testableImports(_ arguments: [String: Any]) -> [String] { - return stringArray(fromArguments: arguments, forKey: "testable") - .map { return "@testable import \($0)" } -} - -/// [Internal] Get value from dictionary -/// - Parameters: -/// - fromArguments: dictionary -/// - forKey: dictionary key -/// - Returns: array of strings, if key not found, returns empty array. -/// - Note: If sourcery arguments containts only one element, then single value is stored, otherwise array of elements. This method always gets array of elements. -func stringArray(fromArguments arguments: [String: Any], forKey key: String) -> [String] { - - if let argument = arguments[key] as? String { - return [argument] - } else if let manyArguments = arguments[key] as? [String] { - return manyArguments - } else { - return [] - } -} -_%> -// Generated with SwiftyMocky 4.2.0 -// Required Sourcery: 1.8.0 - -<%_ for rule in swiftLintRules(argument) { -%> - <%_ %><%= rule %> -<%_ } -%> - -import SwiftyMocky -import XCTest -<%# ================================================== IMPORTS -%><%_ -%> - <%_ for projectImport in projectImports(argument) { -%> - <%_ %><%= projectImport %> - <%_ } -%> - <%# ============================ IMPORTS InAPP (aggregated argument) -%><%_ -%> - <%_ if let swiftyMockyArgs = argument["swiftyMocky"] as? [String: Any] { -%> - <%_ for projectImport in projectImports(swiftyMockyArgs) { -%> - <%_ %><%= projectImport %> - <%_ } -%> - <%_ } -%> -<%_ -class Current { - static var selfType: String = "Self" - static var accessModifier: String = "open" -} -// Collision management -func areThereCollisions(between methods: [MethodWrapper]) -> Bool { - let givenSet = Set(methods.map({ $0.givenConstructorName(prefix: "") })) - guard givenSet.count == methods.count else { return true } // there would be conflicts in Given - let verifySet = Set(methods.map({ $0.verificationProxyConstructorName(prefix: "") })) - guard verifySet.count == methods.count else { return true } // there would be conflicts in Verify - return false -} - -// herlpers -func uniques(methods: [SourceryRuntime.Method]) -> [SourceryRuntime.Method] { - func returnTypeStripped(_ method: SourceryRuntime.Method) -> String { - let returnTypeRaw = "\(method.returnTypeName)" - var stripped: String = { - guard let range = returnTypeRaw.range(of: "where") else { return returnTypeRaw } - var stripped = returnTypeRaw - stripped.removeSubrange((range.lowerBound)...) - return stripped - }() - stripped = stripped.trimmingCharacters(in: CharacterSet(charactersIn: " ")) - return stripped - } - - func areSameParams(_ p1: SourceryRuntime.MethodParameter, _ p2: SourceryRuntime.MethodParameter) -> Bool { - guard p1.argumentLabel == p2.argumentLabel else { return false } - guard p1.name == p2.name else { return false } - guard p1.argumentLabel == p2.argumentLabel else { return false } - guard p1.typeName.name == p2.typeName.name else { return false } - guard p1.actualTypeName?.name == p2.actualTypeName?.name else { return false } - return true - } - - func areSameMethods(_ m1: SourceryRuntime.Method, _ m2: SourceryRuntime.Method) -> Bool { - guard m1.name != m2.name else { return m1.returnTypeName == m2.returnTypeName } - guard m1.selectorName == m2.selectorName else { return false } - guard m1.parameters.count == m2.parameters.count else { return false } - - let p1 = m1.parameters - let p2 = m2.parameters - - for i in 0.. [SourceryRuntime.Method] in - guard !result.contains(where: { areSameMethods($0,element) }) else { return result } - return result + [element] - }) -} - -func uniquesWithoutGenericConstraints(methods: [SourceryRuntime.Method]) -> [SourceryRuntime.Method] { - func returnTypeStripped(_ method: SourceryRuntime.Method) -> String { - let returnTypeRaw = "\(method.returnTypeName)" - var stripped: String = { - guard let range = returnTypeRaw.range(of: "where") else { return returnTypeRaw } - var stripped = returnTypeRaw - stripped.removeSubrange((range.lowerBound)...) - return stripped - }() - stripped = stripped.trimmingCharacters(in: CharacterSet(charactersIn: " ")) - return stripped - } - - func areSameParams(_ p1: SourceryRuntime.MethodParameter, _ p2: SourceryRuntime.MethodParameter) -> Bool { - guard p1.argumentLabel == p2.argumentLabel else { return false } - guard p1.name == p2.name else { return false } - guard p1.argumentLabel == p2.argumentLabel else { return false } - guard p1.typeName.name == p2.typeName.name else { return false } - guard p1.actualTypeName?.name == p2.actualTypeName?.name else { return false } - return true - } - - func areSameMethods(_ m1: SourceryRuntime.Method, _ m2: SourceryRuntime.Method) -> Bool { - guard m1.name != m2.name else { return returnTypeStripped(m1) == returnTypeStripped(m2) } - guard m1.selectorName == m2.selectorName else { return false } - guard m1.parameters.count == m2.parameters.count else { return false } - - let p1 = m1.parameters - let p2 = m2.parameters - - for i in 0.. [SourceryRuntime.Method] in - guard !result.contains(where: { areSameMethods($0,element) }) else { return result } - return result + [element] - }) -} - -func uniques(variables: [SourceryRuntime.Variable]) -> [SourceryRuntime.Variable] { - return variables.reduce([], { (result, element) -> [SourceryRuntime.Variable] in - guard !result.contains(where: { $0.name == element.name }) else { return result } - return result + [element] - }) -} - -func wrapMethod(_ method: SourceryRuntime.Method) -> MethodWrapper { - return MethodWrapper(method) -} - -func wrapSubscript(_ wrapped: SourceryRuntime.Subscript) -> SubscriptWrapper { - return SubscriptWrapper(wrapped) -} - -func justWrap(_ variable: SourceryRuntime.Variable) -> VariableWrapper { return wrapProperty(variable) } -func wrapProperty(_ variable: SourceryRuntime.Variable, _ scope: String = "") -> VariableWrapper { - return VariableWrapper(variable, scope: scope) -} - -func stubProperty(_ variable: SourceryRuntime.Variable, _ scope: String) -> String { - let wrapper = VariableWrapper(variable, scope: scope) - return "\(wrapper.prototype)\n\t\(wrapper.privatePrototype)" -} - -func propertyTypes(_ variable: SourceryRuntime.Variable) -> String { - let wrapper = VariableWrapper(variable, scope: "scope") - return "\(wrapper.propertyGet())" + (wrapper.readonly ? "" : "\n\t\t\(wrapper.propertySet())") -} - -func propertyMethodTypes(_ variable: SourceryRuntime.Variable) -> String { - let wrapper = VariableWrapper(variable, scope: "") - return "\(wrapper.propertyCaseGet())" + (wrapper.readonly ? "" : "\n\t\t\(wrapper.propertyCaseSet())") -} - -func propertyMethodTypesIntValue(_ variable: SourceryRuntime.Variable) -> String { - let wrapper = VariableWrapper(variable, scope: "") - return "\(wrapper.propertyCaseGetIntValue())" + (wrapper.readonly ? "" : "\n\t\t\t\(wrapper.propertyCaseSetIntValue())") -} - -func propertyRegister(_ variable: SourceryRuntime.Variable) { - let wrapper = VariableWrapper(variable, scope: "") - MethodWrapper.register(wrapper.propertyCaseGetName,wrapper.propertyCaseGetName,wrapper.propertyCaseGetName) - guard !wrapper.readonly else { return } - MethodWrapper.register(wrapper.propertyCaseSetName,wrapper.propertyCaseSetName,wrapper.propertyCaseGetName) -} -class Helpers { - static func split(_ string: String, byFirstOccurenceOf word: String) -> (String, String) { - guard let wordRange = string.range(of: word) else { return (string, "") } - let selfRange = string.range(of: string)! - let before = String(string[selfRange.lowerBound.. [String]? { - if let types = annotated.annotations["associatedtype"] as? [String] { - return types.reversed() - } else if let type = annotated.annotations["associatedtype"] as? String { - return [type] - } else { - return nil - } - } - static func extractWhereClause(from annotated: SourceryRuntime.Annotated) -> String? { - if let constraints = annotated.annotations["where"] as? [String] { - return " where \(constraints.reversed().joined(separator: ", "))" - } else if let constraint = annotated.annotations["where"] as? String { - return " where \(constraint)" - } else { - return nil - } - } - /// Extract all typealiases from "annotations" - static func extractTypealiases(from annotated: SourceryRuntime.Annotated) -> [String] { - if let types = annotated.annotations["typealias"] as? [String] { - return types.reversed() - } else if let type = annotated.annotations["typealias"] as? String { - return [type] - } else { - return [] - } - } - static func extractGenericsList(_ associatedTypes: [String]?) -> [String] { - return associatedTypes?.flatMap { - split($0, byFirstOccurenceOf: " where ").0.replacingOccurrences(of: " ", with: "").split(separator: ":").map(String.init).first - }.map { "\($0)" } ?? [] - } - static func extractGenericTypesModifier(_ associatedTypes: [String]?) -> String { - let all = extractGenericsList(associatedTypes) - guard !all.isEmpty else { return "" } - return "<\(all.joined(separator: ","))>" - } - static func extractGenericTypesConstraints(_ associatedTypes: [String]?) -> String { - guard let all = associatedTypes else { return "" } - let constraints = all.flatMap { t -> String? in - let splitted = split(t, byFirstOccurenceOf: " where ") - let constraint = splitted.0.replacingOccurrences(of: " ", with: "").split(separator: ":").map(String.init) - guard constraint.count == 2 else { return nil } - let adopts = constraint[1].split(separator: ",").map(String.init) - var mapped = adopts.map { "\(constraint[0]): \($0)" } - if !splitted.1.isEmpty { - mapped.append(splitted.1) - } - return mapped.joined(separator: ", ") - } - .joined(separator: ", ") - guard !constraints.isEmpty else { return "" } - return " where \(constraints)" - } - static func extractAttributes( - from attributes: [String: [SourceryRuntime.Attribute]], - filterOutStartingWith disallowedPrefixes: [String] = [] - ) -> String { - return attributes - .reduce([SourceryRuntime.Attribute]()) { $0 + $1.1 } - .map { $0.description } - .filter { !["private", "internal", "public", "open", "optional"].contains($0) } - .filter { element in - !disallowedPrefixes.contains(where: element.hasPrefix) - } - .sorted() - .joined(separator: " ") - } -} -class ParameterWrapper { - let parameter: MethodParameter - - var isVariadic = false - - var wrappedForCall: String { - let typeString = "\(type.actualTypeName ?? type)" - let isEscaping = typeString.contains("@escaping") - let isOptional = (type.actualTypeName ?? type).isOptional - if parameter.isClosure && !isEscaping && !isOptional { - return "\(nestedType).any" - } else { - return "\(nestedType).value(\(escapedName))" - } - } - var nestedType: String { - return "\(TypeWrapper(type, isVariadic).nestedParameter)" - } - var justType: String { - return "\(TypeWrapper(type, isVariadic).replacingSelf())" - } - var justPerformType: String { - return "\(TypeWrapper(type, isVariadic).replacingSelfRespectingVariadic())".replacingOccurrences(of: "!", with: "?") - } - var genericType: String { - return isVariadic ? "Parameter<[GenericAttribute]>" : "Parameter" - } - var typeErasedType: String { - return isVariadic ? "Parameter<[TypeErasedAttribute]>" : "Parameter" - } - var type: SourceryRuntime.TypeName { - return parameter.typeName - } - var name: String { - return parameter.name - } - var escapedName: String { - return "`\(parameter.name)`" - } - var comparator: String { - return "guard Parameter.compare(lhs: lhs\(parameter.name.capitalized), rhs: rhs\(parameter.name.capitalized), with: matcher) else { return false }" - } - func comparatorResult() -> String { - let lhsName = "lhs\(parameter.name.capitalized)" - let rhsName = "rhs\(parameter.name.capitalized)" - return "results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: \(lhsName), rhs: \(rhsName), with: matcher), \(lhsName), \(rhsName), \"\(labelAndName())\"))" - } - - init(_ parameter: SourceryRuntime.MethodParameter, _ variadics: [String] = []) { - self.parameter = parameter - self.isVariadic = !variadics.isEmpty && variadics.contains(parameter.name) - } - - func isGeneric(_ types: [String]) -> Bool { - return TypeWrapper(type).isGeneric(types) - } - - func wrappedForProxy(_ generics: [String], _ availability: Bool = false) -> String { - if isGeneric(generics) { - return "\(escapedName).wrapAsGeneric()" - } - if (availability) { - return "\(escapedName).typeErasedAttribute()" - } - return "\(escapedName)" - } - func wrappedForCalls(_ generics: [String], _ availability: Bool = false) -> String { - if isGeneric(generics) { - return "\(wrappedForCall).wrapAsGeneric()" - } - if (availability) { - return "\(wrappedForCall).typeErasedAttribute()" - } - return "\(wrappedForCall)" - } - - func asMethodArgument() -> String { - if parameter.argumentLabel != parameter.name { - return "\(parameter.argumentLabel ?? "_") \(parameter.name): \(parameter.typeName)" - } else { - return "\(parameter.name): \(parameter.typeName)" - } - } - func labelAndName() -> String { - let label = parameter.argumentLabel ?? "_" - return label != parameter.name ? "\(label) \(parameter.name)" : label - } - func sanitizedForEnumCaseName() -> String { - if let label = parameter.argumentLabel, label != parameter.name { - return "\(label)_\(parameter.name)".replacingOccurrences(of: "`", with: "") - } else { - return "\(parameter.name)".replacingOccurrences(of: "`", with: "") - } - } -} -class TypeWrapper { - let type: SourceryRuntime.TypeName - let isVariadic: Bool - - var vPref: String { return isVariadic ? "[" : "" } - var vSuff: String { return isVariadic ? "]" : "" } - - var unwrapped: String { - return type.unwrappedTypeName - } - var unwrappedReplacingSelf: String { - return replacingSelf(unwrap: true) - } - var stripped: String { - if type.isImplicitlyUnwrappedOptional { - return "\(vPref)\(unwrappedReplacingSelf)?\(vSuff)" - } else if type.isOptional { - return "\(vPref)\(unwrappedReplacingSelf)?\(vSuff)" - } else { - return "\(vPref)\(unwrappedReplacingSelf)\(vSuff)" - } - } - var nestedParameter: String { - if type.isImplicitlyUnwrappedOptional { - return "Parameter<\(vPref)\(unwrappedReplacingSelf)?\(vSuff)>" - } else if type.isOptional { - return "Parameter<\(vPref)\(unwrappedReplacingSelf)?\(vSuff)>" - } else { - return "Parameter<\(vPref)\(unwrappedReplacingSelf)\(vSuff)>" - } - } - var isSelfType: Bool { - return unwrapped == "Self" - } - func isSelfTypeRecursive() -> Bool { - if let tuple = type.tuple { - for element in tuple.elements { - guard !TypeWrapper(element.typeName).isSelfTypeRecursive() else { return true } - } - } else if let array = type.array { - return TypeWrapper(array.elementTypeName).isSelfTypeRecursive() - } else if let dictionary = type.dictionary { - guard !TypeWrapper(dictionary.valueTypeName).isSelfTypeRecursive() else { return true } - guard !TypeWrapper(dictionary.keyTypeName).isSelfTypeRecursive() else { return true } - } else if let closure = type.closure { - guard !TypeWrapper(closure.actualReturnTypeName).isSelfTypeRecursive() else { return true } - for parameter in closure.parameters { - guard !TypeWrapper(parameter.typeName).isSelfTypeRecursive() else { return true } - } - } - - return isSelfType - } - - init(_ type: SourceryRuntime.TypeName, _ isVariadic: Bool = false) { - self.type = type - self.isVariadic = isVariadic - } - - func isGeneric(_ types: [String]) -> Bool { - guard !type.isVoid else { return false } - - return isGeneric(name: unwrapped, generics: types) - } - - private func isGeneric(name: String, generics: [String]) -> Bool { - let name = "(\(name.replacingOccurrences(of: " ", with: "")))" - let modifiers = "[\\?\\!]*" - return generics.contains(where: { generic in - let wrapped = "([\\(]\(generic)\(modifiers)[\\)\\.])" - let constraint = "([<,]\(generic)\(modifiers)[>,\\.])" - let arrays = "([\\[:]\(generic)\(modifiers)[\\],\\.:])" - let tuples = "([\\(,]\(generic)\(modifiers)[,\\.\\)])" - let closures = "((\\-\\>)\(generic)\(modifiers)[,\\.\\)])" - let pattern = "\(wrapped)|\(constraint)|\(arrays)|\(tuples)|\(closures)" - guard let regex = try? NSRegularExpression(pattern: pattern) else { return false } - return regex.firstMatch(in: name, options: [], range: NSRange(location: 0, length: (name as NSString).length)) != nil - }) - } - - func replacingSelf(unwrap: Bool = false) -> String { - guard isSelfTypeRecursive() else { - return unwrap ? self.unwrapped : "\(type)" - } - - if isSelfType { - let optionality: String = { - if type.isImplicitlyUnwrappedOptional { - return "!" - } else if type.isOptional { - return "?" - } else { - return "" - } - }() - return unwrap ? Current.selfType : Current.selfType + optionality - } else if let tuple = type.tuple { - let inner = tuple.elements.map({ TypeWrapper($0.typeName).replacingSelf() }).joined(separator: ",") - let value = "(\(inner))" - return value - } else if let array = type.array { - let value = "[\(TypeWrapper(array.elementTypeName).replacingSelf())]" - return value - } else if let dictionary = type.dictionary { - let value = "[" + - "\(TypeWrapper(dictionary.valueTypeName).replacingSelf())" - + ":" + - "\(TypeWrapper(dictionary.keyTypeName).replacingSelf())" - + "]" - return value - } else if let closure = type.closure { - let returnType = TypeWrapper(closure.actualReturnTypeName).replacingSelf() - let inner = closure.parameters - .map { TypeWrapper($0.typeName).replacingSelf() } - .joined(separator: ",") - let throwing = closure.throws ? "throws " : "" - let value = "(\(inner)) \(throwing)-> \(returnType)" - return value - } else { - return (unwrap ? self.unwrapped : "\(type)") - } - } - - func replacingSelfRespectingVariadic() -> String { - return "\(vPref)\(replacingSelf())\(vSuff)" - } -} -func replacingSelf(_ value: String) -> String { - return value - // TODO: proper regex here - // default < case > - .replacingOccurrences(of: "", with: "<\(Current.selfType)>") - .replacingOccurrences(of: "", with: " \(Current.selfType)>") - .replacingOccurrences(of: ",Self>", with: ",\(Current.selfType)>") - // (Self) -> Case - .replacingOccurrences(of: "(Self)", with: "(\(Current.selfType))") - .replacingOccurrences(of: "(Self ", with: "(\(Current.selfType) ") - .replacingOccurrences(of: "(Self.", with: "(\(Current.selfType).") - .replacingOccurrences(of: "(Self,", with: "(\(Current.selfType),") - .replacingOccurrences(of: "(Self?", with: "(\(Current.selfType)?") - .replacingOccurrences(of: " Self)", with: " \(Current.selfType))") - .replacingOccurrences(of: ",Self)", with: ",\(Current.selfType))") - // literals - .replacingOccurrences(of: "[Self]", with: "[\(Current.selfType)]") - // right - .replacingOccurrences(of: "[Self ", with: "[\(Current.selfType) ") - .replacingOccurrences(of: "[Self.", with: "[\(Current.selfType).") - .replacingOccurrences(of: "[Self,", with: "[\(Current.selfType),") - .replacingOccurrences(of: "[Self:", with: "[\(Current.selfType):") - .replacingOccurrences(of: "[Self?", with: "[\(Current.selfType)?") - // left - .replacingOccurrences(of: " Self]", with: " \(Current.selfType)]") - .replacingOccurrences(of: ",Self]", with: ",\(Current.selfType)]") - .replacingOccurrences(of: ":Self]", with: ":\(Current.selfType)]") - // unknown - .replacingOccurrences(of: " Self ", with: " \(Current.selfType) ") - .replacingOccurrences(of: " Self.", with: " \(Current.selfType).") - .replacingOccurrences(of: " Self,", with: " \(Current.selfType),") - .replacingOccurrences(of: " Self:", with: " \(Current.selfType):") - .replacingOccurrences(of: " Self?", with: " \(Current.selfType)?") - .replacingOccurrences(of: ",Self ", with: ",\(Current.selfType) ") - .replacingOccurrences(of: ",Self,", with: ",\(Current.selfType),") - .replacingOccurrences(of: ",Self?", with: ",\(Current.selfType)?") -} - -class MethodWrapper { - private var noStubDefinedMessage: String { - let methodName = method.name.condenseWhitespace() - .replacingOccurrences(of: "( ", with: "(") - .replacingOccurrences(of: " )", with: ")") - return "Stub return value not specified for \(methodName). Use given" - } - private static var registered: [String: Int] = [:] - private static var suffixes: [String: Int] = [:] - private static var suffixesWithoutReturnType: [String: Int] = [:] - - let method: SourceryRuntime.Method - var accessModifier: String { - guard !method.isStatic else { return "public static" } - guard !returnsGenericConstrainedToSelf else { return "public" } - guard !parametersContainsSelf else { return "public" } - return Current.accessModifier - } - var hasAvailability: Bool { method.attributes["available"]?.isEmpty == false } - var isAsync: Bool { - self.method.annotations["async"] != nil - } - - private var registrationName: String { - var rawName = (method.isStatic ? "sm*\(method.selectorName)" : "m*\(method.selectorName)") - .replacingOccurrences(of: "_", with: "") - .replacingOccurrences(of: "(", with: "__") - .replacingOccurrences(of: ")", with: "") - - var parametersNames = method.parameters.map { "\($0.name)" } - - while let range = rawName.range(of: ":"), let name = parametersNames.first { - parametersNames.removeFirst() - rawName.replaceSubrange(range, with: "_\(name)") - } - - let trimSet = CharacterSet(charactersIn: "_") - - return rawName - .replacingOccurrences(of: ":", with: "") - .replacingOccurrences(of: "m*", with: "m_") - .replacingOccurrences(of: "___", with: "__").trimmingCharacters(in: trimSet) - } - private var uniqueName: String { - var rawName = (method.isStatic ? "sm_\(method.selectorName)" : "m_\(method.selectorName)") - var parametersNames = method.parameters.map { "\($0.name)_of_\($0.typeName.name)" } - - while let range = rawName.range(of: ":"), let name = parametersNames.first { - parametersNames.removeFirst() - rawName.replaceSubrange(range, with: "_\(name)") - } - - return rawName.trimmingCharacters(in: CharacterSet(charactersIn: "_")) - } - private var uniqueNameWithReturnType: String { - let returnTypeRaw = "\(method.returnTypeName)" - var returnTypeStripped: String = { - guard let range = returnTypeRaw.range(of: "where") else { return returnTypeRaw } - var stripped = returnTypeRaw - stripped.removeSubrange((range.lowerBound)...) - return stripped - }() - returnTypeStripped = returnTypeStripped.trimmingCharacters(in: CharacterSet(charactersIn: " ")) - return "\(uniqueName)->\(returnTypeStripped)" - } - private var nameSuffix: String { - guard let count = MethodWrapper.registered[registrationName] else { return "" } - guard count > 1 else { return "" } - guard let index = MethodWrapper.suffixes[uniqueNameWithReturnType] else { return "" } - return "_\(index)" - } - private var methodAttributes: String { - return Helpers.extractAttributes(from: self.method.attributes, filterOutStartingWith: ["mutating", "@inlinable"]) - } - private var methodAttributesNonObjc: String { - return Helpers.extractAttributes(from: self.method.attributes, filterOutStartingWith: ["mutating", "@inlinable", "@objc"]) - } - - var prototype: String { - return "\(registrationName)\(nameSuffix)".replacingOccurrences(of: "`", with: "") - } - var parameters: [ParameterWrapper] { - return filteredParameters.map { ParameterWrapper($0, self.getVariadicParametersNames()) } - } - var filteredParameters: [MethodParameter] { - return method.parameters.filter { $0.name != "" } - } - var functionPrototype: String { - let throwing: String = { - if method.throws { - return "throws " - } else if method.rethrows { - return "rethrows " - } else { - return "" - } - }() - - let staticModifier: String = "\(accessModifier) " - let params = replacingSelf(parametersForStubSignature()) - var attributes = self.methodAttributes - attributes = attributes.isEmpty ? "" : "\(attributes)\n\t" - var asyncModifier = self.isAsync ? "async " : "" - - if method.isInitializer { - return "\(attributes)public required \(method.name) \(asyncModifier)\(throwing)" - } else if method.returnTypeName.isVoid { - let wherePartIfNeeded: String = { - if method.returnTypeName.name.hasPrefix("Void") { - let range = method.returnTypeName.name.range(of: "Void")! - return "\(method.returnTypeName.name[range.upperBound...])" - } else { - return !method.returnTypeName.name.isEmpty ? "\(method.returnTypeName.name) " : "" - } - }() - return "\(attributes)\(staticModifier)func \(method.shortName)\(params) \(asyncModifier)\(throwing)\(wherePartIfNeeded)" - } else if returnsGenericConstrainedToSelf { - return "\(attributes)\(staticModifier)func \(method.shortName)\(params) \(asyncModifier)\(throwing)-> \(returnTypeReplacingSelf) " - } else { - return "\(attributes)\(staticModifier)func \(method.shortName)\(params) \(asyncModifier)\(throwing)-> \(method.returnTypeName.name) " - } - } - var invocation: String { - guard !method.isInitializer else { return "" } - if filteredParameters.isEmpty { - return "addInvocation(.\(prototype))" - } else { - return "addInvocation(.\(prototype)(\(parametersForMethodCall())))" - } - } - var givenValue: String { - guard !method.isInitializer else { return "" } - guard method.throws || !method.returnTypeName.isVoid else { return "" } - - let methodType = filteredParameters.isEmpty ? ".\(prototype)" : ".\(prototype)(\(parametersForMethodCall()))" - let returnType: String = returnsSelf ? "__Self__" : "\(TypeWrapper(method.returnTypeName).stripped)" - - if method.returnTypeName.isVoid { - return """ - \n\t\tdo { - \t\t _ = try methodReturnValue(\(methodType)).casted() as Void - \t\t}\(" ") - """ - } else { - let defaultValue = method.returnTypeName.isOptional ? " = nil" : "" - return """ - \n\t\tvar __value: \(returnType)\(defaultValue) - \t\tdo { - \t\t __value = try methodReturnValue(\(methodType)).casted() - \t\t}\(" ") - """ - } - } - var throwValue: String { - guard !method.isInitializer else { return "" } - guard method.throws || !method.returnTypeName.isVoid else { return "" } - let safeFailure = method.isStatic ? "" : "\t\t\tonFatalFailure(\"\(noStubDefinedMessage)\")\n" - // For Void and Returning optionals - we allow not stubbed case to happen, as we are still able to return - let noStubHandling = method.returnTypeName.isVoid || method.returnTypeName.isOptional ? "\t\t\t// do nothing" : "\(safeFailure)\t\t\tFailure(\"\(noStubDefinedMessage)\")" - guard method.throws else { - return """ - catch { - \(noStubHandling) - \t\t} - """ - } - - return """ - catch MockError.notStubed { - \(noStubHandling) - \t\t} catch { - \t\t throw error - \t\t} - """ - } - var returnValue: String { - guard !method.isInitializer else { return "" } - guard !method.returnTypeName.isVoid else { return "" } - - return "\n\t\treturn __value" - } - var equalCase: String { - guard !method.isInitializer else { return "" } - - if filteredParameters.isEmpty { - return "case (.\(prototype), .\(prototype)):" - } else { - let lhsParams = filteredParameters.map { "let lhs\($0.name.capitalized)" }.joined(separator: ", ") - let rhsParams = filteredParameters.map { "let rhs\($0.name.capitalized)" }.joined(separator: ", ") - return "case (.\(prototype)(\(lhsParams)), .\(prototype)(\(rhsParams))):" - } - } - func equalCases() -> String { - var results = self.equalCase - - guard !parameters.isEmpty else { - results += " return .match" - return results - } - - results += "\n\t\t\t\tvar results: [Matcher.ParameterComparisonResult] = []\n" - results += parameters.map { "\t\t\t\t\($0.comparatorResult())" }.joined(separator: "\n") - results += "\n\t\t\t\treturn Matcher.ComparisonResult(results)" - return results - } - var intValueCase: String { - if filteredParameters.isEmpty { - return "case .\(prototype): return 0" - } else { - let params = filteredParameters.enumerated().map { offset, _ in - return "p\(offset)" - } - let definitions = params.joined(separator: ", ") - let paramsSum = params.map({ "\($0).intValue" }).joined(separator: " + ") - return "case let .\(prototype)(\(definitions)): return \(paramsSum)" - } - } - var assertionName: String { - return "case .\(prototype): return \".\(method.selectorName)\(method.parameters.isEmpty ? "()" : "")\"" - } - - var returnsSelf: Bool { - guard !returnsGenericConstrainedToSelf else { return true } - return !method.returnTypeName.isVoid && TypeWrapper(method.returnTypeName).isSelfType - } - var returnsGenericConstrainedToSelf: Bool { - let defaultReturnType = "\(method.returnTypeName.name) " - return defaultReturnType != returnTypeReplacingSelf - } - var returnTypeReplacingSelf: String { - return replacingSelf("\(method.returnTypeName.name) ") - } - var parametersContainsSelf: Bool { - return replacingSelf(parametersForStubSignature()) != parametersForStubSignature() - } - - var replaceSelf: String { - return Current.selfType - } - - init(_ method: SourceryRuntime.Method) { - self.method = method - } - - public static func clear() -> String { - MethodWrapper.registered = [:] - MethodWrapper.suffixes = [:] - MethodWrapper.suffixesWithoutReturnType = [:] - return "" - } - - func register() { - MethodWrapper.register(registrationName,uniqueName,uniqueNameWithReturnType) - } - - static func register(_ name: String, _ uniqueName: String, _ uniqueNameWithReturnType: String) { - if let count = MethodWrapper.registered[name] { - MethodWrapper.registered[name] = count + 1 - MethodWrapper.suffixes[uniqueNameWithReturnType] = count + 1 - } else { - MethodWrapper.registered[name] = 1 - MethodWrapper.suffixes[uniqueNameWithReturnType] = 1 - } - - if let count = MethodWrapper.suffixesWithoutReturnType[uniqueName] { - MethodWrapper.suffixesWithoutReturnType[uniqueName] = count + 1 - } else { - MethodWrapper.suffixesWithoutReturnType[uniqueName] = 1 - } - } - - func returnTypeMatters() -> Bool { - let count = MethodWrapper.suffixesWithoutReturnType[uniqueName] ?? 0 - return count > 1 - } - - func wrappedInMethodType() -> Bool { - return !method.isInitializer - } - - func returningParameter(_ multiple: Bool, _ front: Bool) -> String { - guard returnTypeMatters() else { return "" } - let returning: String = "returning: \(returnTypeStripped(method, type: true))" - guard multiple else { return returning } - - return front ? ", \(returning)" : "\(returning), " - } - - // Stub - func stubBody() -> String { - let body: String = { - if method.isInitializer || !returnsSelf { - return invocation + performCall() + givenValue + throwValue + returnValue - } else { - return wrappedStubPrefix() - + "\t\t" + invocation - + performCall() - + givenValue - + throwValue - + returnValue - + wrappedStubPostfix() - } - }() - return replacingSelf(body) - } - - func wrappedStubPrefix() -> String { - guard !method.isInitializer, returnsSelf else { - return "" - } - - let throwing: String = { - if method.throws { - return "throws " - } else if method.rethrows { - return "rethrows " - } else { - return "" - } - }() - - return "func _wrapped<__Self__>() \(throwing)-> __Self__ {\n" - } - - func wrappedStubPostfix() -> String { - guard !method.isInitializer, returnsSelf else { - return "" - } - - let throwing: String = (method.throws || method.rethrows) ? "try ": "" - - return "\n\t\t}" - + "\n\t\treturn \(throwing)_wrapped()" - } - - // Method Type - func methodTypeDeclarationWithParameters() -> String { - if filteredParameters.isEmpty { - return "case \(prototype)" - } else { - return "case \(prototype)(\(parametersForMethodTypeDeclaration(availability: hasAvailability)))" - } - } - - // Given - func containsEmptyArgumentLabels() -> Bool { - return parameters.contains(where: { $0.parameter.argumentLabel == nil }) - } - - func givenReturnTypeString() -> String { - let returnTypeString: String = { - guard !returnsGenericConstrainedToSelf else { return returnTypeReplacingSelf } - guard !returnsSelf else { return replaceSelf } - return TypeWrapper(method.returnTypeName).stripped - }() - return returnTypeString - } - - func givenConstructorName(prefix: String = "") -> String { - let returnTypeString = givenReturnTypeString() - let (annotation, _, _) = methodInfo() - let clauseConstraints = whereClauseExpression() - - if filteredParameters.isEmpty { - return "\(annotation)public static func \(method.shortName)(willReturn: \(returnTypeString)...) -> \(prefix)MethodStub" + clauseConstraints - } else { - return "\(annotation)public static func \(method.shortName)(\(parametersForProxySignature()), willReturn: \(returnTypeString)...) -> \(prefix)MethodStub" + clauseConstraints - } - } - - func givenConstructorNameThrows(prefix: String = "") -> String { - let (annotation, _, _) = methodInfo() - let clauseConstraints = whereClauseExpression() - - let genericsArray = getGenericsConstraints(getGenericsAmongParameters(), filterSingle: false) - let generics = genericsArray.isEmpty ? "" : "<\(genericsArray.joined(separator: ", "))>" - - if filteredParameters.isEmpty { - return "\(annotation)public static func \(method.callName)\(generics)(willThrow: Error...) -> \(prefix)MethodStub" + clauseConstraints - } else { - return "\(annotation)public static func \(method.callName)\(generics)(\(parametersForProxySignature()), willThrow: Error...) -> \(prefix)MethodStub" + clauseConstraints - } - } - - func givenConstructor(prefix: String = "") -> String { - if filteredParameters.isEmpty { - return "return \(prefix)Given(method: .\(prototype), products: willReturn.map({ StubProduct.return($0 as Any) }))" - } else { - return "return \(prefix)Given(method: .\(prototype)(\(parametersForProxyInit())), products: willReturn.map({ StubProduct.return($0 as Any) }))" - } - } - - func givenConstructorThrows(prefix: String = "") -> String { - if filteredParameters.isEmpty { - return "return \(prefix)Given(method: .\(prototype), products: willThrow.map({ StubProduct.throw($0) }))" - } else { - return "return \(prefix)Given(method: .\(prototype)(\(parametersForProxyInit())), products: willThrow.map({ StubProduct.throw($0) }))" - } - } - - // Given willProduce - func givenProduceConstructorName(prefix: String = "") -> String { - let returnTypeString = givenReturnTypeString() - let (annotation, _, _) = methodInfo() - let produceClosure = "(Stubber<\(returnTypeString)>) -> Void" - let clauseConstraints = whereClauseExpression() - - if filteredParameters.isEmpty { - return "\(annotation)public static func \(method.shortName)(willProduce: \(produceClosure)) -> \(prefix)MethodStub" + clauseConstraints - } else { - return "\(annotation)public static func \(method.shortName)(\(parametersForProxySignature()), willProduce: \(produceClosure)) -> \(prefix)MethodStub" + clauseConstraints - } - } - - func givenProduceConstructorNameThrows(prefix: String = "") -> String { - let returnTypeString = givenReturnTypeString() - let (annotation, _, _) = methodInfo() - let produceClosure = "(StubberThrows<\(returnTypeString)>) -> Void" - let clauseConstraints = whereClauseExpression() - - if filteredParameters.isEmpty { - return "\(annotation)public static func \(method.shortName)(willProduce: \(produceClosure)) -> \(prefix)MethodStub" + clauseConstraints - } else { - return "\(annotation)public static func \(method.shortName)(\(parametersForProxySignature()), willProduce: \(produceClosure)) -> \(prefix)MethodStub" + clauseConstraints - } - } - - func givenProduceConstructor(prefix: String = "") -> String { - let returnTypeString = givenReturnTypeString() - return """ - let willReturn: [\(returnTypeString)] = [] - \t\t\tlet given: \(prefix)Given = { \(givenConstructor(prefix: prefix)) }() - \t\t\tlet stubber = given.stub(for: (\(returnTypeString)).self) - \t\t\twillProduce(stubber) - \t\t\treturn given - """ - } - - func givenProduceConstructorThrows(prefix: String = "") -> String { - let returnTypeString = givenReturnTypeString() - return """ - let willThrow: [Error] = [] - \t\t\tlet given: \(prefix)Given = { \(givenConstructorThrows(prefix: prefix)) }() - \t\t\tlet stubber = given.stubThrows(for: (\(returnTypeString)).self) - \t\t\twillProduce(stubber) - \t\t\treturn given - """ - } - - // Verify - func verificationProxyConstructorName(prefix: String = "") -> String { - let (annotation, methodName, genericConstrains) = methodInfo() - - if filteredParameters.isEmpty { - return "\(annotation)public static func \(methodName)(\(returningParameter(false,true))) -> \(prefix)Verify\(genericConstrains)" - } else { - return "\(annotation)public static func \(methodName)(\(parametersForProxySignature())\(returningParameter(true,true))) -> \(prefix)Verify\(genericConstrains)" - } - } - - func verificationProxyConstructor(prefix: String = "") -> String { - if filteredParameters.isEmpty { - return "return \(prefix)Verify(method: .\(prototype))" - } else { - return "return \(prefix)Verify(method: .\(prototype)(\(parametersForProxyInit())))" - } - } - - // Perform - func performProxyConstructorName(prefix: String = "") -> String { - let body: String = { - let (annotation, methodName, genericConstrains) = methodInfo() - - if filteredParameters.isEmpty { - return "\(annotation)public static func \(methodName)(\(returningParameter(true,false))perform: @escaping \(performProxyClosureType())) -> \(prefix)Perform\(genericConstrains)" - } else { - return "\(annotation)public static func \(methodName)(\(parametersForProxySignature()), \(returningParameter(true,false))perform: @escaping \(performProxyClosureType())) -> \(prefix)Perform\(genericConstrains)" - } - }() - return replacingSelf(body) - } - - func performProxyConstructor(prefix: String = "") -> String { - if filteredParameters.isEmpty { - return "return \(prefix)Perform(method: .\(prototype), performs: perform)" - } else { - return "return \(prefix)Perform(method: .\(prototype)(\(parametersForProxyInit())), performs: perform)" - } - } - - func performProxyClosureType() -> String { - if filteredParameters.isEmpty { - return "() -> Void" - } else { - let parameters = self.parameters - .map { "\($0.justPerformType)" } - .joined(separator: ", ") - return "(\(parameters)) -> Void" - } - } - - func performProxyClosureCall() -> String { - if filteredParameters.isEmpty { - return "perform?()" - } else { - let parameters = filteredParameters - .map { p in - let wrapped = ParameterWrapper(p, self.getVariadicParametersNames()) - let isAutolosure = wrapped.justType.hasPrefix("@autoclosure") - return "\(p.inout ? "&" : "")`\(p.name)`\(isAutolosure ? "()" : "")" - } - .joined(separator: ", ") - return "perform?(\(parameters))" - } - } - - func performCall() -> String { - guard !method.isInitializer else { return "" } - let type = performProxyClosureType() - var proxy = filteredParameters.isEmpty ? "\(prototype)" : "\(prototype)(\(parametersForMethodCall()))" - - let cast = "let perform = methodPerformValue(.\(proxy)) as? \(type)" - let call = performProxyClosureCall() - - return "\n\t\t\(cast)\n\t\t\(call)" - } - - // Helpers - private func parametersForMethodCall() -> String { - let generics = getGenericsWithoutConstraints() - return parameters.map { $0.wrappedForCalls(generics, hasAvailability) }.joined(separator: ", ") - } - - private func parametersForMethodTypeDeclaration(availability: Bool) -> String { - let generics = getGenericsWithoutConstraints() - return parameters.map { param in - if param.isGeneric(generics) { return param.genericType } - if availability { return param.typeErasedType } - return replacingSelf(param.nestedType) - }.joined(separator: ", ") - } - - private func parametersForProxySignature() -> String { - return parameters.map { p in - return "\(p.labelAndName()): \(replacingSelf(p.nestedType))" - }.joined(separator: ", ") - } - - private func parametersForStubSignature() -> String { - func replacing(first: String, in full: String, with other: String) -> String { - guard let range = full.range(of: first) else { return full } - return full.replacingCharacters(in: range, with: other) - } - let prefix = method.shortName - let full = method.name - let range = full.range(of: prefix)! - var unrefined = "\(full[range.upperBound...])" - parameters.map { p -> (String,String) in - return ("\(p.type)","\(p.justType)") - }.forEach { - unrefined = replacing(first: $0, in: unrefined, with: $1) - } - return unrefined - } - - private func parametersForProxyInit() -> String { - let generics = getGenericsWithoutConstraints() - return parameters.map { "\($0.wrappedForProxy(generics, hasAvailability))" }.joined(separator: ", ") - } - - private func isGeneric() -> Bool { - return method.shortName.contains("<") && method.shortName.contains(">") - } - - private func getVariadicParametersNames() -> [String] { - let pattern = "[\\(|,]( *[_|\\w]* )? *(\\w+) *\\: *(.+?\\.\\.\\.)" - let str = method.name - let range = NSRange(location: 0, length: (str as NSString).length) - - guard let regex = try? NSRegularExpression(pattern: pattern) else { return [] } - - var result: [String] = regex - .matches(in: str, options: [], range: range) - .compactMap { match -> String? in - guard let nameRange = Range(match.range(at: 2), in: str) else { return nil } - return String(str[nameRange]) - } - return result - } - - /// Returns list of generics used in method signature, without their constraints (like [T,U,V]) - /// - /// - Returns: Array of strings, where each strings represent generic name - private func getGenericsWithoutConstraints() -> [String] { - let name = method.shortName - guard let start = name.index(of: "<"), let end = name.index(of: ">") else { return [] } - - var genPart = name[start...end] - genPart.removeFirst() - genPart.removeLast() - - let parts = genPart.replacingOccurrences(of: " ", with: "").split(separator: ",").map(String.init) - return parts.map { stripGenPart(part: $0) } - } - - /// Returns list of generic constraintes from method signature. Does only contain stuff between '<' and '>' - /// - /// - Returns: Array of strings, like ["T: Codable", "U: Whatever"] - private func getGenericsConstraints(_ generics: [String], filterSingle: Bool = true) -> [String] { - let name = method.shortName - guard let start = name.index(of: "<"), let end = name.index(of: ">") else { return [] } - - var genPart = name[start...end] - genPart.removeFirst() - genPart.removeLast() - - let parts = genPart.replacingOccurrences(of: " ", with: "").split(separator: ",").map(String.init) - return parts.filter { - let components = $0.components(separatedBy: ":") - return (components.count == 2 || !filterSingle) && generics.contains(components[0]) - } - } - - private func getGenericsAmongParameters() -> [String] { - return getGenericsWithoutConstraints().filter { - for param in self.parameters { - if param.isGeneric([$0]) { return true } - } - return false - } - } - - private func wrapGenerics(_ generics: [String]) -> String { - guard !generics.isEmpty else { return "" } - return "<\(generics.joined(separator:","))>" - } - - private func stripGenPart(part: String) -> String { - return part.split(separator: ":").map(String.init).first! - } - - private func returnTypeStripped(_ method: SourceryRuntime.Method, type: Bool = false) -> String { - let returnTypeRaw = "\(method.returnTypeName)" - var stripped: String = { - guard let range = returnTypeRaw.range(of: "where") else { return returnTypeRaw } - var stripped = returnTypeRaw - stripped.removeSubrange((range.lowerBound)...) - return stripped - }() - stripped = stripped.trimmingCharacters(in: CharacterSet(charactersIn: " ")) - guard type else { return stripped } - return "(\(stripped)).Type" - } - - private func whereClauseConstraints() -> [String] { - let returnTypeRaw = method.returnTypeName.name - guard let range = returnTypeRaw.range(of: "where") else { return [] } - var whereClause = returnTypeRaw - whereClause.removeSubrange(...(range.upperBound)) - return whereClause - .trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - .components(separatedBy: ",") - } - - private func whereClauseExpression() -> String { - let constraints = whereClauseConstraints() - if constraints.isEmpty { - return "" - } - return " where " + constraints.joined(separator: ", ") - } - - private func methodInfo() -> (annotation: String, methodName: String, genericConstrains: String) { - let generics = getGenericsAmongParameters() - let methodName = returnTypeMatters() ? method.shortName : "\(method.callName)\(wrapGenerics(generics))" - let constraints: String = { - let constraints: [String] - if returnTypeMatters() { - constraints = whereClauseConstraints() - } else { - constraints = getGenericsConstraints(generics) - } - guard !constraints.isEmpty else { return "" } - - return " where \(constraints.joined(separator: ", "))" - }() - var attributes = self.methodAttributesNonObjc - attributes = attributes.condenseWhitespace() - attributes = attributes.isEmpty ? "" : "\(attributes)\n\t\t" - return (attributes, methodName, constraints) - } -} - -extension String { - func condenseWhitespace() -> String { - let components = self.components(separatedBy: .whitespacesAndNewlines) - return components.filter { !$0.isEmpty }.joined(separator: " ") - } -} -class SubscriptWrapper { - let wrapped: SourceryRuntime.Subscript - var readonly: Bool { return !wrapped.isMutable } - var wrappedParameters: [ParameterWrapper] { return wrapped.parameters.map { ParameterWrapper($0) } } - var casesCount: Int { return readonly ? 1 : 2 } - var nestedType: String { return "\(TypeWrapper(wrapped.returnTypeName).nestedParameter)" } - let associatedTypes: [String]? - let genericTypesList: [String] - let genericTypesModifier: String? - let whereClause: String - var hasAvailability: Bool { wrapped.attributes["available"]?.isEmpty == false } - - private var methodAttributes: String { - return Helpers.extractAttributes(from: self.wrapped.attributes, filterOutStartingWith: ["mutating", "@inlinable"]) - } - private var methodAttributesNonObjc: String { - return Helpers.extractAttributes(from: self.wrapped.attributes, filterOutStartingWith: ["mutating", "@inlinable", "@objc"]) - } - - private let noStubDefinedMessage = "Stub return value not specified for subscript. Use given first." - - private static var registered: [String: Int] = [:] - private static var namesWithoutReturnType: [String: Int] = [:] - private static var suffixes: [String: Int] = [:] - public static func clear() -> String { - SubscriptWrapper.registered = [:] - SubscriptWrapper.suffixes = [:] - namesWithoutReturnType = [:] - return "" - } - static func register(_ name: String, _ uniqueName: String) { - let count = SubscriptWrapper.registered[name] ?? 0 - SubscriptWrapper.registered[name] = count + 1 - SubscriptWrapper.suffixes[uniqueName] = count + 1 - } - static func register(short name: String) { - let count = SubscriptWrapper.namesWithoutReturnType[name] ?? 0 - SubscriptWrapper.namesWithoutReturnType[name] = count + 1 - } - - func register() { - SubscriptWrapper.register(registrationName("get"),uniqueName) - SubscriptWrapper.register(short: shortName) - guard !readonly else { return } - SubscriptWrapper.register(registrationName("set"),uniqueName) - } - - init(_ wrapped: SourceryRuntime.Subscript) { - self.wrapped = wrapped - associatedTypes = Helpers.extractAssociatedTypes(from: wrapped) - genericTypesList = Helpers.extractGenericsList(associatedTypes) - whereClause = Helpers.extractWhereClause(from: wrapped) ?? "" - if let types = associatedTypes { - genericTypesModifier = "<\(types.joined(separator: ","))>" - } else { - genericTypesModifier = nil - } - } - - func registrationName(_ accessor: String) -> String { - return "subscript_\(accessor)_\(wrappedParameters.map({ $0.sanitizedForEnumCaseName() }).joined(separator: "_"))" - } - var shortName: String { return "public subscript\(genericTypesModifier ?? " ")(\(wrappedParameters.map({ $0.asMethodArgument() }).joined(separator: ", ")))" } - var uniqueName: String { return "\(shortName) -> \(wrapped.returnTypeName)\(self.whereClause)" } - - private func nameSuffix(_ accessor: String) -> String { - guard let count = SubscriptWrapper.registered[registrationName(accessor)] else { return "" } - guard count > 1 else { return "" } - guard let index = SubscriptWrapper.suffixes[uniqueName] else { return "" } - return "_\(index)" - } - - // call - func subscriptCall() -> String { - let get = "\n\t\tget {\(getter())\n\t\t}" - let set = readonly ? "" : "\n\t\tset {\(setter())\n\t\t}" - var attributes = self.methodAttributesNonObjc - attributes = attributes.isEmpty ? "" : "\(attributes)\n\t" - return "\(attributes)\(uniqueName) {\(get)\(set)\n\t}" - } - private func getter() -> String { - let method = ".\(subscriptCasePrefix("get"))(\(parametersForMethodCall()))" - let optionalReturnWorkaround = "\(wrapped.returnTypeName)".hasSuffix("?") - let noStubDefined = (optionalReturnWorkaround || wrapped.returnTypeName.isOptional) ? "return nil" : "onFatalFailure(\"\(noStubDefinedMessage)\"); Failure(\"noStubDefinedMessage\")" - return - "\n\t\t\taddInvocation(\(method))" + - "\n\t\t\tdo {" + - "\n\t\t\t\treturn try methodReturnValue(\(method)).casted()" + - "\n\t\t\t} catch {" + - "\n\t\t\t\t\(noStubDefined)" + - "\n\t\t\t}" - } - private func setter() -> String { - let method = ".\(subscriptCasePrefix("set"))(\(parametersForMethodCall(set: true)))" - return "\n\t\t\taddInvocation(\(method))" - } - - var assertionName: String { - return readonly ? assertionName("get") : "\(assertionName("get"))\n\t\t\t\(assertionName("set"))" - } - private func assertionName(_ accessor: String) -> String { - return "case .\(subscriptCasePrefix(accessor)): return " + - "\"[\(accessor)] `subscript`\(genericTypesModifier ?? "")[\(parametersForAssertionName())]\"" - } - - // method type - func subscriptCasePrefix(_ accessor: String) -> String { - return "\(registrationName(accessor))\(nameSuffix(accessor))" - } - func subscriptCaseName(_ accessor: String, availability: Bool = false) -> String { - return "\(subscriptCasePrefix(accessor))(\(parametersForMethodTypeDeclaration(availability: availability, set: accessor == "set")))" - } - func subscriptCases() -> String { - if readonly { - return "case \(subscriptCaseName("get", availability: hasAvailability))" - } else { - return "case \(subscriptCaseName("get", availability: hasAvailability))\n\t\tcase \(subscriptCaseName("set", availability: hasAvailability))" - } - } - func equalCase(_ accessor: String) -> String { - var lhsParams = wrapped.parameters.map { "lhs\($0.name.capitalized)" }.joined(separator: ", ") - var rhsParams = wrapped.parameters.map { "rhs\($0.name.capitalized)" }.joined(separator: ", ") - var comparators = "\t\t\t\tvar results: [Matcher.ParameterComparisonResult] = []\n" - comparators += wrappedParameters.map { "\t\t\t\t\($0.comparatorResult())" }.joined(separator: "\n") - - if accessor == "set" { - lhsParams += ", lhsDidSet" - rhsParams += ", rhsDidSet" - comparators += "\n\t\t\t\tresults.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDidSet, rhs: rhsDidSet, with: matcher), lhsDidSet, rhsDidSet, \"newValue\"))" - } - - comparators += "\n\t\t\t\treturn Matcher.ComparisonResult(results)" - - // comparatorResult() - return "case (let .\(subscriptCasePrefix(accessor))(\(lhsParams)), let .\(subscriptCasePrefix(accessor))(\(rhsParams))):\n" + comparators - } - func equalCases() -> String { - return readonly ? equalCase("get") : "\(equalCase("get"))\n\t\t\t\(equalCase("set"))" - } - func intValueCase() -> String { - return readonly ? intValueCase("get") : "\(intValueCase("get"))\n\t\t\t\(intValueCase("set"))" - } - func intValueCase(_ accessor: String) -> String { - let params = wrappedParameters.enumerated().map { offset, _ in - return "p\(offset)" - } - let definitions = params.joined(separator: ", ") + (accessor == "set" ? ", _" : "") - let paramsSum = params.map({ "\($0).intValue" }).joined(separator: " + ") - return "case let .\(subscriptCasePrefix(accessor))(\(definitions)): return \(paramsSum)" - } - - // Given - func givenConstructorName() -> String { - let returnTypeString = returnsSelf ? replaceSelf : TypeWrapper(wrapped.returnTypeName).stripped - var attributes = self.methodAttributesNonObjc - attributes = attributes.isEmpty ? "" : "\(attributes)\n\t\t" - return "\(attributes)public static func `subscript`\(genericTypesModifier ?? "")(\(parametersForProxySignature()), willReturn: \(returnTypeString)...) -> SubscriptStub" - } - func givenConstructor() -> String { - return "return Given(method: .\(subscriptCasePrefix("get"))(\(parametersForProxyInit())), products: willReturn.map({ StubProduct.return($0 as Any) }))" - } - - // Verify - func verifyConstructorName(set: Bool = false) -> String { - let returnTypeString = returnsSelf ? replaceSelf : nestedType - let returning = set ? "" : returningParameter(true, true) - var attributes = self.methodAttributesNonObjc - attributes = attributes.isEmpty ? "" : "\(attributes)\n\t\t" - return "\(attributes)public static func `subscript`\(genericTypesModifier ?? "")(\(parametersForProxySignature())\(returning)\(set ? ", set newValue: \(returnTypeString)" : "")) -> Verify" - } - func verifyConstructor(set: Bool = false) -> String { - return "return Verify(method: .\(subscriptCasePrefix(set ? "set" : "get"))(\(parametersForProxyInit(set: set))))" - } - - // Generics - private func getGenerics() -> [String] { - return genericTypesList - } - - // Helpers - private var returnsSelf: Bool { return TypeWrapper(wrapped.returnTypeName).isSelfType } - private var replaceSelf: String { return Current.selfType } - private func returnTypeStripped(type: Bool = false) -> String { - let returnTypeRaw = "\(wrapped.returnTypeName)" - var stripped: String = { - guard let range = returnTypeRaw.range(of: "where") else { return returnTypeRaw } - var stripped = returnTypeRaw - stripped.removeSubrange((range.lowerBound)...) - return stripped - }() - stripped = stripped.trimmingCharacters(in: CharacterSet(charactersIn: " ")) - guard type else { return stripped } - return "(\(stripped)).Type" - } - private func returnTypeMatters() -> Bool { - let count = SubscriptWrapper.namesWithoutReturnType[shortName] ?? 0 - return count > 1 - } - - // params - private func returningParameter(_ multiple: Bool, _ front: Bool) -> String { - guard returnTypeMatters() else { return "" } - let returning: String = "returning: \(returnTypeStripped(type: true))" - guard multiple else { return returning } - return front ? ", \(returning)" : "\(returning), " - } - private func parametersForMethodTypeDeclaration(availability: Bool = false, set: Bool = false) -> String { - let generics: [String] = getGenerics() - let params = wrappedParameters.map { param in - if param.isGeneric(generics) { return param.genericType } - if availability { return param.typeErasedType } - return param.nestedType - }.joined(separator: ", ") - guard set else { return params } - let newValue = TypeWrapper(wrapped.returnTypeName).isGeneric(generics) ? "Parameter" : nestedType - return "\(params), \(newValue)" - } - private func parametersForProxyInit(set: Bool = false) -> String { - let generics = getGenerics() - let newValue = TypeWrapper(wrapped.returnTypeName).isGeneric(generics) ? "newValue.wrapAsGeneric()" : "newValue" - return wrappedParameters.map { "\($0.wrappedForProxy(generics, hasAvailability))" }.joined(separator: ", ") + (set ? ", \(newValue)" : "") - } - private func parametersForProxySignature(set: Bool = false) -> String { - return wrappedParameters.map { "\($0.labelAndName()): \($0.nestedType)" }.joined(separator: ", ") + (set ? ", set newValue: \(nestedType)" : "") - } - private func parametersForAssertionName() -> String { - return wrappedParameters.map { "\($0.labelAndName())" }.joined(separator: ", ") - } - private func parametersForMethodCall(set: Bool = false) -> String { - let generics = getGenerics() - let params = wrappedParameters.map { $0.wrappedForCalls(generics, hasAvailability) }.joined(separator: ", ") - let postfix = TypeWrapper(wrapped.returnTypeName).isGeneric(generics) ? ".wrapAsGeneric()" : "" - return !set ? params : "\(params), \(nestedType).value(newValue)\(postfix)" - } -} -class VariableWrapper { - let variable: SourceryRuntime.Variable - let scope: String - var readonly: Bool { return variable.writeAccess.isEmpty } - var privatePrototypeName: String { return "__p_\(variable.name)".replacingOccurrences(of: "`", with: "") } - var casesCount: Int { return readonly ? 1 : 2 } - - var accessModifier: String { - // TODO: Fix access levels for SwiftyPrototype - // guard variable.type?.accessLevel != "internal" else { return "" } - return "public " - } - var attributes: String { - let value = Helpers.extractAttributes(from: self.variable.attributes) - return value.isEmpty ? "\(accessModifier)" : "\(value)\n\t\t\(accessModifier)" - } - var noStubDefinedMessage: String { return "\(scope) - stub value for \(variable.name) was not defined" } - - var getter: String { - let staticModifier = variable.isStatic ? "\(scope)." : "" - let returnValue = variable.isOptional ? "optionalGivenGetterValue(.\(propertyCaseGetName), \"\(noStubDefinedMessage)\")" : "givenGetterValue(.\(propertyCaseGetName), \"\(noStubDefinedMessage)\")" - return "\n\t\tget {\t\(staticModifier)invocations.append(.\(propertyCaseGetName)); return \(staticModifier)\(privatePrototypeName) ?? \(returnValue) }" - } - var setter: String { - let staticModifier = variable.isStatic ? "\(scope)." : "" - if readonly { - return "" - } else { - return "\n\t\tset {\t\(staticModifier)invocations.append(.\(propertyCaseSetName)(.value(newValue))); \(variable.isStatic ? "\(scope)." : "")\(privatePrototypeName) = newValue }" - } - } - var prototype: String { - let staticModifier = variable.isStatic ? "static " : "" - - return "\(attributes)\(staticModifier)var \(variable.name): \(variable.typeName.name) {" + - "\(getter)" + - "\(setter)" + - "\n\t}" - } - var assertionName: String { - var result = "case .\(propertyCaseGetName): return \"[get] .\(variable.name)\"" - if !readonly { - result += "\n\t\t\tcase .\(propertyCaseSetName): return \"[set] .\(variable.name)\"" - } - return result - } - - var privatePrototype: String { - let staticModifier = variable.isStatic ? "static " : "" - var typeName = "\(variable.typeName.unwrappedTypeName)" - let isWrappedInBrackets = typeName.hasPrefix("(") && typeName.hasSuffix(")") - if !isWrappedInBrackets { - typeName = "(\(typeName))" - } - return "private \(staticModifier)var \(privatePrototypeName): \(typeName)?" - } - var nestedType: String { return "\(TypeWrapper(variable.typeName).nestedParameter)" } - - init(_ variable: SourceryRuntime.Variable, scope: String) { - self.variable = variable - self.scope = scope - } - - func compareCases() -> String { - var result = propertyCaseGetCompare() - if !readonly { - result += "\n\t\t\t\(propertyCaseSetCompare())" - } - return result - } - - func propertyGet() -> String { - let staticModifier = variable.isStatic ? "Static" : "" - return "public static var \(variable.name): \(staticModifier)Verify { return \(staticModifier)Verify(method: .\(propertyCaseGetName)) }" - } - - func propertySet() -> String { - let staticModifier = variable.isStatic ? "Static" : "" - return "public static func \(variable.name)(set newValue: \(nestedType)) -> \(staticModifier)Verify { return \(staticModifier)Verify(method: .\(propertyCaseSetName)(newValue)) }" - } - - var propertyCaseGetName: String { return "p_\(variable.name)_get".replacingOccurrences(of: "`", with: "") } - func propertyCaseGet() -> String { - return "case \(propertyCaseGetName)" - } - func propertyCaseGetCompare() -> String { - return "case (.\(propertyCaseGetName),.\(propertyCaseGetName)): return Matcher.ComparisonResult.match" - } - func propertyCaseGetIntValue() -> String { - return "case .\(propertyCaseGetName): return 0" - } - - var propertyCaseSetName: String { return "p_\(variable.name)_set".replacingOccurrences(of: "`", with: "") } - func propertyCaseSet() -> String { - return "case \(propertyCaseSetName)(\(nestedType))" - } - func propertyCaseSetCompare() -> String { - let lhsName = "left" - let rhsName = "right" - let comaprison = "Matcher.ParameterComparisonResult(\(nestedType).compare(lhs: \(lhsName), rhs: \(rhsName), with: matcher), \(lhsName), \(rhsName), \"newValue\")" - let result = "Matcher.ComparisonResult([\(comaprison)])" - return "case (.\(propertyCaseSetName)(let left),.\(propertyCaseSetName)(let right)): return \(result)" - } - func propertyCaseSetIntValue() -> String { - return "case .\(propertyCaseSetName)(let newValue): return newValue.intValue" - } - - // Given - func givenConstructorName(prefix: String = "") -> String { - return "\(attributes)static func \(variable.name)(getter defaultValue: \(TypeWrapper(variable.typeName).stripped)...) -> \(prefix)PropertyStub" - } - - func givenConstructor(prefix: String = "") -> String { - return "return \(prefix)Given(method: .\(propertyCaseGetName), products: defaultValue.map({ StubProduct.return($0 as Any) }))" - } -} -_%> -<%# ================================================== SETUP -%><%_ -%> -<%_ var all = types.all - all += types.protocols.map { $0 } - all += types.protocolCompositions.map { $0 } - var mockedCount = 0 --%> - -<%_ for type in all { -%><%_ -%> -<%_ let autoMockable: Bool = type.inheritedTypes.contains("AutoMockable") || type.annotations["AutoMockable"] != nil - let protocolToDecorate = types.protocols.first(where: { $0.name == (type.annotations["mock"] as? String) }) - let inlineMockable = protocolToDecorate != nil - guard let aProtocol = autoMockable ? type : protocolToDecorate else { continue } - mockedCount += 1 - - let associatedTypes: [String]? = Helpers.extractAssociatedTypes(from: aProtocol) - let attributes: String = Helpers.extractAttributes(from: type.attributes) - let typeAliases: [String] = Helpers.extractTypealiases(from: aProtocol) - let genericTypesModifier: String = Helpers.extractGenericTypesModifier(associatedTypes) - let genericTypesConstraints: String = Helpers.extractGenericTypesConstraints(associatedTypes) - let allSubscripts = aProtocol.allSubscripts - let allVariables = uniques(variables: aProtocol.allVariables.filter({ !$0.isStatic })) - let containsVariables = !allVariables.isEmpty - let allStaticVariables = uniques(variables: aProtocol.allVariables.filter({ $0.isStatic })) - let containsStaticVariables = !allStaticVariables.isEmpty - let allMethods = uniques(methods: aProtocol.allMethods.filter({ !$0.isStatic || $0.isInitializer })) - let selfConstrained = allMethods.map(wrapMethod).contains(where: { $0.returnsGenericConstrainedToSelf || $0.parametersContainsSelf }) - let accessModifier: String = selfConstrained ? "public final" : "open" - Current.accessModifier = accessModifier // TODO: Temporary workaround for access modifiers - let inheritFromNSObject = type.annotations["ObjcProtocol"] != nil || attributes.contains("@objc") - let allMethodsForMethodType = uniquesWithoutGenericConstraints(methods: aProtocol.allMethods.filter({ !$0.isStatic })) - let allStaticMethods = uniques(methods: aProtocol.allMethods.filter({ $0.isStatic && !$0.isInitializer })) - let allStaticMethodsForMethodType = uniquesWithoutGenericConstraints(methods: aProtocol.allMethods.filter({ $0.isStatic })) - let conformsToStaticMock = !allStaticMethods.isEmpty || !allStaticVariables.isEmpty - let conformsToMock = !allMethods.isEmpty || !allVariables.isEmpty -%><%_ -%><%_ -%> -<%_ if autoMockable { -%> -// MARK: - <%= type.name %> -<%= attributes %> -<%= accessModifier %> class <%= type.name %><%= mockTypeName %><%= genericTypesModifier %>:<%= inheritFromNSObject ? " NSObject," : "" %> <%= type.name %>, Mock<%= conformsToStaticMock ? ", StaticMock" : "" %><%= genericTypesConstraints %> { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - -<%_ } else { -%> -// sourcery:inline:auto:<%= type.name %>.autoMocked -<%_ } -%> -<%# ================================================== MAIN CLASS -%><%_ -%> - <%# ================================================== MOCK INTERNALS -%><%_ -%> - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - <%_ for typeAlias in typeAliases { -%> - public typealias <%= typeAlias %> - <%_ } %> <%_ -%> - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - <%_ -%> - <%# ================================================== STATIC MOCK INTERNALS -%><%_ -%> - <%_ if conformsToStaticMock { -%> - static var matcher: Matcher = Matcher.default - static var stubbingPolicy: StubbingPolicy = .wrap - static var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - static private var queue = DispatchQueue(label: "com.swiftymocky.invocations.static", qos: .userInteractive) - static private var invocations: [StaticMethodType] = [] - static private var methodReturnValues: [StaticGiven] = [] - static private var methodPerformValues: [StaticPerform] = [] - public typealias StaticPropertyStub = StaticGiven - public typealias StaticMethodStub = StaticGiven - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public static func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - <%_ } -%> - - <%# ================================================== VARIABLES -%><%_ -%> - <%_ for variable in allVariables { -%> - <%_ if autoMockable { -%> - <%= stubProperty(variable,"\(type.name)\(mockTypeName)") %> - <%_ } else { %> - <%= stubProperty(variable,"\(type.name)") %> - <%_ } %> - <%_ } %> <%_ -%> - - <%# ================================================== STATIC VARIABLES -%><%_ -%> - <%_ for variable in allStaticVariables { -%> - <%_ if autoMockable { -%> - <%= stubProperty(variable,"\(type.name)\(mockTypeName)") %> - <%_ } else { %> - <%= stubProperty(variable,"\(type.name)") %> - <%_ } %> - <%_ } %> <%_ -%> - - <%# ================================================== METHOD REGISTRATIONS -%><%_ -%> - <%_ MethodWrapper.clear() -%> - <%_ SubscriptWrapper.clear() -%> - <%_ if autoMockable { -%> - <%_ Current.selfType = "\(type.name)\(mockTypeName)\(genericTypesModifier)" -%> - <%_ } else { %> - <%_ Current.selfType = "\(type.name)\(mockTypeName)\(genericTypesModifier)" -%> - <%_ } %> - <%_ let wrappedSubscripts = allSubscripts.map(wrapSubscript) -%> - <%_ let wrappedMethods = allMethods.map(wrapMethod).filter({ $0.wrappedInMethodType() }) -%> - <%_ let wrappedVariables = allVariables.map(justWrap) -%> - <%_ let wrappedMethodsForMethodType = allMethodsForMethodType.map(wrapMethod).filter({ $0.wrappedInMethodType() }) -%> - <%_ let wrappedInitializers = allMethods.map(wrapMethod).filter({ $0.method.isInitializer }) -%> - <%_ let wrappedStaticMethods = allStaticMethods.map(wrapMethod).filter({ $0.wrappedInMethodType() }) -%> - <%_ let wrappedStaticVariables = allStaticVariables.map(justWrap) -%> - <%_ let wrappedStaticMethodsForMethodType = allStaticMethodsForMethodType.map(wrapMethod).filter({ $0.wrappedInMethodType() }) -%> - <%_ for variable in allVariables { propertyRegister(variable) } -%> - <%_ for variable in allStaticVariables { propertyRegister(variable) } -%> - <%_ for method in wrappedMethods { method.register() } -%> - <%_ for wrapped in wrappedSubscripts { wrapped.register() } -%> - <%_ for method in wrappedStaticMethods { method.register() } -%><%_ -%> - <%_ let variableCasesCount: Int = wrappedVariables.reduce(0) { return $0 + $1.casesCount } -%><%_ -%> - <%_ let subscriptsCasesCount: Int = wrappedSubscripts.reduce(0) { return $0 + $1.casesCount } -%><%_ -%> - <%_ let staticVariableCasesCount: Int = wrappedStaticVariables.reduce(0) { return $0 + $1.casesCount } -%><%_ -%> - - <%# ================================================== STATIC STUBS -%><%_ -%> - <%_ for method in wrappedStaticMethods { -%> - <%= method.functionPrototype _%> { - <%= method.stubBody() _%> - } - - <%_ } %><%_ -%> - <%_ -%> - <%# ================================================== INITIALIZERS -%><%_ -%> - <%_ for method in wrappedInitializers { -%> - <%= method.functionPrototype _%> { } - - <%_ } -%><%_ -%> - <%_ -%><%_ -%> - <%# ================================================== STUBS -%><%_ -%> - <%_ for method in wrappedMethods { -%> - <%= method.functionPrototype _%> { - <%= method.stubBody() _%> - } - - <%_ } -%> - <%_ for wrapped in wrappedSubscripts { -%> - <%= wrapped.subscriptCall() _%> - - <%_ } -%> - <%# ================================================== STATIC METHOD TYPE -%><%_ -%> - <%_ if conformsToStaticMock { -%> - fileprivate enum StaticMethodType { - <%_ for method in wrappedStaticMethodsForMethodType { -%> - <%= method.methodTypeDeclarationWithParameters() _%> - <%_ } %> <%_ for variable in allStaticVariables { -%> - <%= propertyMethodTypes(variable) %> - <%_ } %> <%_ %> - <%_ -%> - static func compareParameters(lhs: StaticMethodType, rhs: StaticMethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { <%_ for method in wrappedStaticMethodsForMethodType { %> - <%= method.equalCases() %> - <%_ } %> <%_ for variable in wrappedStaticVariables { -%> - <%= variable.compareCases() %> - <%_ } %> <%_ -%> <%_ if wrappedStaticMethods.count + staticVariableCasesCount > 1 { -%> - default: return .none - <%_ } -%> - } - } - <%_ %> - func intValue() -> Int { - switch self { <%_ for method in wrappedStaticMethodsForMethodType { %> - <%= method.intValueCase -%><% } %> - <%_ for variable in allStaticVariables { -%> - <%= propertyMethodTypesIntValue(variable) %> - <%_ } %> <%_ -%> - } - } - func assertionName() -> String { - switch self { <%_ for method in wrappedStaticMethodsForMethodType { %> - <%= method.assertionName -%><% } %> - <%_ for variable in wrappedStaticVariables { -%> - <%= variable.assertionName %> - <%_ } %> - } - } - } - - open class StaticGiven: StubbedMethod { - fileprivate var method: StaticMethodType - - private init(method: StaticMethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - <%_ for variable in allStaticVariables { -%> - <%= wrapProperty(variable).givenConstructorName(prefix: "Static") -%> { - <%= wrapProperty(variable).givenConstructor(prefix: "Static") _%> - } - <%_ } %> <%_ %> - <%_ for method in wrappedStaticMethodsForMethodType.filter({ !$0.method.returnTypeName.isVoid && !$0.method.isInitializer }) { -%> - <%= method.givenConstructorName(prefix: "Static") -%> { - <%= method.givenConstructor(prefix: "Static") _%> - } - <%_ } -%> - <%_ for method in wrappedStaticMethodsForMethodType.filter({ !$0.method.throws && !$0.method.rethrows && !$0.method.returnTypeName.isVoid && !$0.method.isInitializer }) { -%> - <%= method.givenProduceConstructorName(prefix: "Static") -%> { - <%= method.givenProduceConstructor(prefix: "Static") _%> - } - <%_ } -%> - <%_ for method in wrappedStaticMethodsForMethodType.filter({ ($0.method.throws || $0.method.rethrows) && !$0.method.isInitializer }) { -%> - <%= method.givenConstructorNameThrows(prefix: "Static") -%> { - <%= method.givenConstructorThrows(prefix: "Static") _%> - } - <%= method.givenProduceConstructorNameThrows(prefix: "Static") -%> { - <%= method.givenProduceConstructorThrows(prefix: "Static") _%> - } - <%_ } %> <%_ -%> - } - - public struct StaticVerify { - fileprivate var method: StaticMethodType - - <%_ for method in wrappedStaticMethodsForMethodType { -%> - <%= method.verificationProxyConstructorName(prefix: "Static") -%> { <%= method.verificationProxyConstructor(prefix: "Static") _%> } - <%_ } %> <%_ -%> - <%_ for variable in allStaticVariables { -%> - <%= propertyTypes(variable) %> - <%_ } %> <%_ -%> - } - - public struct StaticPerform { - fileprivate var method: StaticMethodType - var performs: Any - - <%_ for method in wrappedStaticMethodsForMethodType { -%> - <%= method.performProxyConstructorName(prefix: "Static") -%> { - <%= method.performProxyConstructor(prefix: "Static") _%> - } - <%_ } %> <%_ -%> - } - - <% } -%> - <%# ================================================== METHOD TYPE -%><%_ -%> - <%_ if !wrappedMethods.isEmpty || !allVariables.isEmpty || !allSubscripts.isEmpty { -%> - - fileprivate enum MethodType { - <%_ for method in wrappedMethodsForMethodType { -%> - <%= method.methodTypeDeclarationWithParameters() _%> - <%_ } -%> <%_ for variable in allVariables { -%> - <%= propertyMethodTypes(variable) %> - <%_ } %> <%_ %> <%_ for wrapped in wrappedSubscripts { -%> - <%= wrapped.subscriptCases() _%> - <%_ } %> <%_ %> - <%_ -%> - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { <%_ for method in wrappedMethodsForMethodType { %> - <%= method.equalCases() %> - <%_ } %> <%_ for variable in wrappedVariables { -%> - <%= variable.compareCases() %> - <%_ } %> <%_ -%> <%_ for wrapped in wrappedSubscripts { -%> - <%= wrapped.equalCases() %> - <%_ } %> <%_ if wrappedMethods.count + variableCasesCount + subscriptsCasesCount > 1 { -%> - default: return .none - <%_ } -%> - } - } - <%_ %> - func intValue() -> Int { - switch self { <%_ for method in wrappedMethodsForMethodType { %> - <%= method.intValueCase -%><% } %> - <%_ for variable in allVariables { -%> - <%= propertyMethodTypesIntValue(variable) %> - <%_ } %> <%_ for wrapped in wrappedSubscripts { -%> - <%= wrapped.intValueCase() %> - <%_ } -%> - } - } - func assertionName() -> String { - switch self { <%_ for method in wrappedMethodsForMethodType { %> - <%= method.assertionName -%><% } %> - <%_ for variable in wrappedVariables { -%> - <%= variable.assertionName %> - <%_ } %> <%_ for wrapped in wrappedSubscripts { -%> - <%= wrapped.assertionName %> - <%_ } -%> - } - } - } - <%_ } else { %> - fileprivate struct MethodType { - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { return .match } - func intValue() -> Int { return 0 } - func assertionName() -> String { return "" } - } - <%_ } -%><%_ -%> - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - <%_ for variable in allVariables { -%> - <%= wrapProperty(variable).givenConstructorName() -%> { - <%= wrapProperty(variable).givenConstructor() _%> - } - <%_ } %> <%_ %> - <%_ for method in wrappedMethodsForMethodType.filter({ !$0.method.returnTypeName.isVoid && !$0.method.isInitializer }) { -%> - <%= method.givenConstructorName() -%> { - <%= method.givenConstructor() _%> - } - <%_ } -%> - <%_ for method in wrappedMethodsForMethodType.filter({ !$0.method.throws && !$0.method.rethrows && !$0.method.returnTypeName.isVoid && !$0.method.isInitializer }) { -%> - <%= method.givenProduceConstructorName() -%> { - <%= method.givenProduceConstructor() _%> - } - <%_ } -%> - <%_ for wrapped in wrappedSubscripts { -%> - <%= wrapped.givenConstructorName() -%> { - <%= wrapped.givenConstructor() _%> - } - <%_ } -%> - <%_ for method in wrappedMethodsForMethodType.filter({ ($0.method.throws || $0.method.rethrows) && !$0.method.isInitializer }) { -%> - <%= method.givenConstructorNameThrows() -%> { - <%= method.givenConstructorThrows() _%> - } - <%= method.givenProduceConstructorNameThrows() -%> { - <%= method.givenProduceConstructorThrows() _%> - } - <%_ } %> <%_ -%> - } - - public struct Verify { - fileprivate var method: MethodType - - <%_ for method in wrappedMethodsForMethodType { -%> - <%= method.verificationProxyConstructorName() -%> { <%= method.verificationProxyConstructor() _%> } - <%_ } %> <%_ -%> - <%_ for variable in allVariables { -%> - <%= propertyTypes(variable) %> - <%_ } %> <%_ -%> - <%_ for wrapped in wrappedSubscripts { -%> - <%= wrapped.verifyConstructorName() -%> { <%= wrapped.verifyConstructor() _%> } - <%_ if !wrapped.readonly { -%> - <%= wrapped.verifyConstructorName(set: true) -%> { <%= wrapped.verifyConstructor(set: true) _%> } - <%_ } -%> - <%_ } %> <%_ -%> - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - <%_ for method in wrappedMethodsForMethodType { -%> - <%= method.performProxyConstructorName() -%> { - <%= method.performProxyConstructor() _%> - } - <%_ } %> <%_ -%> - } - - <%# ================================================== MOCK METHODS -%><%_ -%> - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } - <%# ================================================== STATIC MOCK METHODS -%><%_ -%> - <%_ if conformsToStaticMock { -%> - - static public func given(_ method: StaticGiven) { - methodReturnValues.append(method) - } - - static public func perform(_ method: StaticPerform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - static public func verify(_ method: StaticVerify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return StaticMethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - static private func addInvocation(_ call: StaticMethodType) { - self.queue.sync { invocations.append(call) } - } - static private func methodReturnValue(_ method: StaticMethodType) throws -> StubProduct { - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && StaticMethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - static private func methodPerformValue(_ method: StaticMethodType) -> Any? { - let matched = methodPerformValues.reversed().first { StaticMethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - static private func matchingCalls(_ method: StaticMethodType, file: StaticString?, line: UInt?) -> [StaticMethodType] { - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return invocations.filter { StaticMethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - static private func matchingCalls(_ method: StaticVerify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - static private func givenGetterValue(_ method: StaticMethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - Failure(message) - } - } - static private func optionalGivenGetterValue(_ method: StaticMethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - <%_ } -%> -<%_ if autoMockable { -%> -} - -<%_ } else { -%> -// sourcery:end -<%_ } -%> -<% } -%> -<%_ if mockedCount == 0 { -%> -// SwiftyMocky: no AutoMockable found. -// Please define and inherit from AutoMockable, or annotate protocols to be mocked -<%_ } -%> diff --git a/OpenEdX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/OpenEdX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index de56fd23a..afdfaeed3 100644 --- a/OpenEdX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/OpenEdX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,204 +1,204 @@ { - "originHash": "679c9881c55ee7e1f6d683f7cf7aae4fd8777f05e38f2cce8c6d21aa216ec03b", - "pins": [ + "originHash" : "679c9881c55ee7e1f6d683f7cf7aae4fd8777f05e38f2cce8c6d21aa216ec03b", + "pins" : [ { - "identity": "abseil-cpp-binary", - "kind": "remoteSourceControl", - "location": "https://github.com/google/abseil-cpp-binary.git", - "state": { - "revision": "194a6706acbd25e4ef639bcaddea16e8758a3e27", - "version": "1.2024011602.0" + "identity" : "abseil-cpp-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/abseil-cpp-binary.git", + "state" : { + "revision" : "194a6706acbd25e4ef639bcaddea16e8758a3e27", + "version" : "1.2024011602.0" } }, { - "identity": "alamofire", - "kind": "remoteSourceControl", - "location": "https://github.com/Alamofire/Alamofire.git", - "state": { - "revision": "e16d3481f5ed35f0472cb93350085853d754913f", - "version": "5.10.1" + "identity" : "alamofire", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Alamofire/Alamofire.git", + "state" : { + "revision" : "513364f870f6bfc468f9d2ff0a95caccc10044c5", + "version" : "5.10.2" } }, { - "identity": "app-check", - "kind": "remoteSourceControl", - "location": "https://github.com/google/app-check.git", - "state": { - "revision": "87dd288fc792bf9751e522e171a47df5b783b0b8", - "version": "11.1.0" + "identity" : "app-check", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/app-check.git", + "state" : { + "revision" : "87dd288fc792bf9751e522e171a47df5b783b0b8", + "version" : "11.1.0" } }, { - "identity": "firebase-ios-sdk", - "kind": "remoteSourceControl", - "location": "https://github.com/firebase/firebase-ios-sdk", - "state": { - "revision": "f909f901bfba9e27e4e9da83242a4915d6dd64bb", - "version": "11.3.0" + "identity" : "firebase-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/firebase-ios-sdk", + "state" : { + "revision" : "f909f901bfba9e27e4e9da83242a4915d6dd64bb", + "version" : "11.3.0" } }, { - "identity": "googleappmeasurement", - "kind": "remoteSourceControl", - "location": "https://github.com/google/GoogleAppMeasurement.git", - "state": { - "revision": "93406fd21b85e66e2d6dbf50b472161fd75c3f1f", - "version": "11.3.0" + "identity" : "googleappmeasurement", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleAppMeasurement.git", + "state" : { + "revision" : "93406fd21b85e66e2d6dbf50b472161fd75c3f1f", + "version" : "11.3.0" } }, { - "identity": "googledatatransport", - "kind": "remoteSourceControl", - "location": "https://github.com/google/GoogleDataTransport.git", - "state": { - "revision": "617af071af9aa1d6a091d59a202910ac482128f9", - "version": "10.1.0" + "identity" : "googledatatransport", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleDataTransport.git", + "state" : { + "revision" : "617af071af9aa1d6a091d59a202910ac482128f9", + "version" : "10.1.0" } }, { - "identity": "googleutilities", - "kind": "remoteSourceControl", - "location": "https://github.com/google/GoogleUtilities.git", - "state": { - "revision": "53156c7ec267db846e6b64c9f4c4e31ba4cf75eb", - "version": "8.0.2" + "identity" : "googleutilities", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleUtilities.git", + "state" : { + "revision" : "53156c7ec267db846e6b64c9f4c4e31ba4cf75eb", + "version" : "8.0.2" } }, { - "identity": "grpc-binary", - "kind": "remoteSourceControl", - "location": "https://github.com/google/grpc-binary.git", - "state": { - "revision": "f56d8fc3162de9a498377c7b6cea43431f4f5083", - "version": "1.65.1" + "identity" : "grpc-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/grpc-binary.git", + "state" : { + "revision" : "f56d8fc3162de9a498377c7b6cea43431f4f5083", + "version" : "1.65.1" } }, { - "identity": "gtm-session-fetcher", - "kind": "remoteSourceControl", - "location": "https://github.com/google/gtm-session-fetcher.git", - "state": { - "revision": "a2ab612cb980066ee56d90d60d8462992c07f24b", - "version": "3.5.0" + "identity" : "gtm-session-fetcher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/gtm-session-fetcher.git", + "state" : { + "revision" : "a2ab612cb980066ee56d90d60d8462992c07f24b", + "version" : "3.5.0" } }, { - "identity": "interop-ios-for-google-sdks", - "kind": "remoteSourceControl", - "location": "https://github.com/google/interop-ios-for-google-sdks.git", - "state": { - "revision": "2d12673670417654f08f5f90fdd62926dc3a2648", - "version": "100.0.0" + "identity" : "interop-ios-for-google-sdks", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/interop-ios-for-google-sdks.git", + "state" : { + "revision" : "2d12673670417654f08f5f90fdd62926dc3a2648", + "version" : "100.0.0" } }, { - "identity": "keychain-swift", - "kind": "remoteSourceControl", - "location": "https://github.com/evgenyneu/keychain-swift.git", - "state": { - "revision": "5e1b02b6a9dac2a759a1d5dbc175c86bd192a608", - "version": "24.0.0" + "identity" : "keychain-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/evgenyneu/keychain-swift.git", + "state" : { + "revision" : "5e1b02b6a9dac2a759a1d5dbc175c86bd192a608", + "version" : "24.0.0" } }, { - "identity": "kingfisher", - "kind": "remoteSourceControl", - "location": "https://github.com/onevcat/Kingfisher.git", - "state": { - "revision": "c0940e241945e6378c01fbd45fd3815579d47ef5", - "version": "8.1.0" + "identity" : "kingfisher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/onevcat/Kingfisher.git", + "state" : { + "revision" : "2015fda791daa72c8058619545a593bf8c1dd59f", + "version" : "8.5.0" } }, { - "identity": "leveldb", - "kind": "remoteSourceControl", - "location": "https://github.com/firebase/leveldb.git", - "state": { - "revision": "a0bc79961d7be727d258d33d5a6b2f1023270ba1", - "version": "1.22.5" + "identity" : "leveldb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/leveldb.git", + "state" : { + "revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1", + "version" : "1.22.5" } }, { - "identity": "microsoft-authentication-library-for-objc", - "kind": "remoteSourceControl", - "location": "https://github.com/AzureAD/microsoft-authentication-library-for-objc", - "state": { - "revision": "332bc5a808099da0ee82c27eefa57f763bc76fd5", - "version": "1.8.1" + "identity" : "microsoft-authentication-library-for-objc", + "kind" : "remoteSourceControl", + "location" : "https://github.com/AzureAD/microsoft-authentication-library-for-objc", + "state" : { + "revision" : "332bc5a808099da0ee82c27eefa57f763bc76fd5", + "version" : "1.8.1" } }, { - "identity": "nanopb", - "kind": "remoteSourceControl", - "location": "https://github.com/firebase/nanopb.git", - "state": { - "revision": "b7e1104502eca3a213b46303391ca4d3bc8ddec1", - "version": "2.30910.0" + "identity" : "nanopb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/nanopb.git", + "state" : { + "revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1", + "version" : "2.30910.0" } }, { - "identity": "openedx-app-firebase-analytics-ios", - "kind": "remoteSourceControl", - "location": "https://github.com/openedx/openedx-app-firebase-analytics-ios", - "state": { - "revision": "99d440b38ad73d3d829c8ec669c03acbf95bbb6b", - "version": "1.0.3" + "identity" : "openedx-app-firebase-analytics-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/openedx/openedx-app-firebase-analytics-ios", + "state" : { + "revision" : "99d440b38ad73d3d829c8ec669c03acbf95bbb6b", + "version" : "1.0.3" } }, { - "identity": "openedx-app-foundation-ios", - "kind": "remoteSourceControl", - "location": "https://github.com/openedx/openedx-app-foundation-ios/", - "state": { - "revision": "61259adc491ad73689c5731cfd0af5142198bd73", - "version": "1.0.4" + "identity" : "openedx-app-foundation-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/openedx/openedx-app-foundation-ios/", + "state" : { + "revision" : "61259adc491ad73689c5731cfd0af5142198bd73", + "version" : "1.0.4" } }, { - "identity": "promises", - "kind": "remoteSourceControl", - "location": "https://github.com/google/promises.git", - "state": { - "revision": "540318ecedd63d883069ae7f1ed811a2df00b6ac", - "version": "2.4.0" + "identity" : "promises", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/promises.git", + "state" : { + "revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac", + "version" : "2.4.0" } }, { - "identity": "swift-protobuf", - "kind": "remoteSourceControl", - "location": "https://github.com/apple/swift-protobuf.git", - "state": { - "revision": "ebc7251dd5b37f627c93698e4374084d98409633", - "version": "1.28.2" + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "ebc7251dd5b37f627c93698e4374084d98409633", + "version" : "1.28.2" } }, { - "identity": "swiftlintplugins", - "kind": "remoteSourceControl", - "location": "https://github.com/SimplyDanny/SwiftLintPlugins", - "state": { - "revision": "7c80ce6f142164b0201871e580b021d1b2c69804", - "version": "0.57.0" + "identity" : "swiftlintplugins", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SimplyDanny/SwiftLintPlugins", + "state" : { + "revision" : "6166499ede0efe43c3809f101d2c3cd409e2b77a", + "version" : "0.61.0" } }, { - "identity": "swiftui-introspect", - "kind": "remoteSourceControl", - "location": "https://github.com/siteline/swiftui-introspect", - "state": { - "revision": "807f73ce09a9b9723f12385e592b4e0aaebd3336", - "version": "1.3.0" + "identity" : "swiftui-introspect", + "kind" : "remoteSourceControl", + "location" : "https://github.com/siteline/swiftui-introspect", + "state" : { + "revision" : "a08b87f96b41055577721a6e397562b21ad52454", + "version" : "26.0.0" } }, { - "identity": "swinject", - "kind": "remoteSourceControl", - "location": "https://github.com/Swinject/Swinject.git", - "state": { - "revision": "be9dbcc7b86811bc131539a20c6f9c2d3e56919f", - "version": "2.9.1" + "identity" : "swinject", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Swinject/Swinject.git", + "state" : { + "revision" : "b685b549fe4d8ae265fc7a2f27d0789720425d69", + "version" : "2.10.0" } } ], - "version": 3 + "version" : 3 } diff --git a/OpenEdX/Managers/AnalyticsManager/MainScreenAnalytics.swift b/OpenEdX/Managers/AnalyticsManager/MainScreenAnalytics.swift index 566b6dbc2..d2ff8a43a 100644 --- a/OpenEdX/Managers/AnalyticsManager/MainScreenAnalytics.swift +++ b/OpenEdX/Managers/AnalyticsManager/MainScreenAnalytics.swift @@ -7,7 +7,6 @@ import Foundation -//sourcery: AutoMockable public protocol MainScreenAnalytics: Sendable { func mainDiscoveryTabClicked() func mainLearnTabClicked() @@ -21,7 +20,7 @@ public protocol MainScreenAnalytics: Sendable { } #if DEBUG -final public class MainScreenAnalyticsMock: MainScreenAnalytics { +final public class MainScreenAnalyticsPreviewMock: MainScreenAnalytics { public func mainDiscoveryTabClicked() {} public func mainLearnTabClicked() {} public func mainDownloadsTabClicked() {} diff --git a/OpenEdX/Managers/DeepLinkManager/DeepLinkManager.swift b/OpenEdX/Managers/DeepLinkManager/DeepLinkManager.swift index 7ae93eb7e..ef6b746c5 100644 --- a/OpenEdX/Managers/DeepLinkManager/DeepLinkManager.swift +++ b/OpenEdX/Managers/DeepLinkManager/DeepLinkManager.swift @@ -15,7 +15,6 @@ import Profile import OEXFoundation // swiftlint:disable function_body_length -//sourcery: AutoMockable @MainActor public protocol DeepLinkService { func configureWith( diff --git a/Podfile b/Podfile index 4bdfad284..eb03e1874 100644 --- a/Podfile +++ b/Podfile @@ -18,97 +18,97 @@ abstract_target "App" do workspace './Core/Core.xcodeproj' target 'CoreTests' do - pod 'SwiftyMocky', :git => 'https://github.com/MakeAWishFoundation/SwiftyMocky.git', :branch => 'master' + # Migrated to Mockolo end end target "Authorization" do project './Authorization/Authorization.xcodeproj' workspace './Authorization/Authorization.xcodeproj' - + target 'AuthorizationTests' do - pod 'SwiftyMocky', :git => 'https://github.com/MakeAWishFoundation/SwiftyMocky.git', :branch => 'master' + # Migrated to Mockolo end end - + target "Discovery" do project './Discovery/Discovery.xcodeproj' workspace './Discovery/Discovery.xcodeproj' - + target 'DiscoveryUnitTests' do - pod 'SwiftyMocky', :git => 'https://github.com/MakeAWishFoundation/SwiftyMocky.git', :branch => 'master' + # Migrated to Mockolo end end - + target "WhatsNew" do project './WhatsNew/WhatsNew.xcodeproj' workspace './WhatsNew/WhatsNew.xcodeproj' - + target 'WhatsNewTests' do - pod 'SwiftyMocky', :git => 'https://github.com/MakeAWishFoundation/SwiftyMocky.git', :branch => 'master' + # Migrated to Mockolo end end - + target "Dashboard" do project './Dashboard/Dashboard.xcodeproj' workspace './Dashboard/Dashboard.xcodeproj' - + target 'DashboardTests' do - pod 'SwiftyMocky', :git => 'https://github.com/MakeAWishFoundation/SwiftyMocky.git', :branch => 'master' + # Migrated to Mockolo end end - + target "Downloads" do project './Downloads/Downloads.xcodeproj' workspace './Downloads/Downloads.xcodeproj' - + target 'DownloadsTests' do - pod 'SwiftyMocky', :git => 'https://github.com/MakeAWishFoundation/SwiftyMocky.git', :branch => 'master' + # Migrated to Mockolo end end - + target "Profile" do project './Profile/Profile.xcodeproj' workspace './Profile/Profile.xcodeproj' - + target 'ProfileTests' do - pod 'SwiftyMocky', :git => 'https://github.com/MakeAWishFoundation/SwiftyMocky.git', :branch => 'master' + # Migrated to Mockolo end end - + target "Course" do project './Course/Course.xcodeproj' workspace './Course/Course.xcodeproj' - + target 'CourseTests' do - pod 'SwiftyMocky', :git => 'https://github.com/MakeAWishFoundation/SwiftyMocky.git', :branch => 'master' + # Migrated to Mockolo end end - + target "AppDates" do project './AppDates/AppDates.xcodeproj' workspace './AppDates/AppDates.xcodeproj' - + target 'AppDatesTests' do - pod 'SwiftyMocky', :git => 'https://github.com/MakeAWishFoundation/SwiftyMocky.git', :branch => 'master' + # Migrated to Mockolo end end - + target "Discussion" do project './Discussion/Discussion.xcodeproj' workspace './Discussion/Discussion.xcodeproj' - + target 'DiscussionTests' do - pod 'SwiftyMocky', :git => 'https://github.com/MakeAWishFoundation/SwiftyMocky.git', :branch => 'master' + # Migrated to Mockolo end end - + target "Theme" do project './Theme/Theme.xcodeproj' workspace './Theme/Theme.xcodeproj' - + target 'ThemeTests' do - pod 'SwiftyMocky', :git => 'https://github.com/MakeAWishFoundation/SwiftyMocky.git', :branch => 'master' + # Migrated to Mockolo end end diff --git a/Podfile.lock b/Podfile.lock index e4af30cb1..6795b60e8 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,39 +1,20 @@ PODS: - - Sourcery (1.8.0): - - Sourcery/CLI-Only (= 1.8.0) - - Sourcery/CLI-Only (1.8.0) - SwiftGen (6.6.3) - SwiftLint (0.57.0) - - SwiftyMocky (4.2.0): - - Sourcery (= 1.8.0) DEPENDENCIES: - SwiftGen (~> 6.6) - SwiftLint (~> 0.57.0) - - SwiftyMocky (from `https://github.com/MakeAWishFoundation/SwiftyMocky.git`, branch `master`) SPEC REPOS: trunk: - - Sourcery - SwiftGen - SwiftLint -EXTERNAL SOURCES: - SwiftyMocky: - :branch: master - :git: https://github.com/MakeAWishFoundation/SwiftyMocky.git - -CHECKOUT OPTIONS: - SwiftyMocky: - :commit: 3672eea08c7098214ac54ee26c7a7e39ea01a2f1 - :git: https://github.com/MakeAWishFoundation/SwiftyMocky.git - SPEC CHECKSUMS: - Sourcery: 6f5fe49b82b7e02e8c65560cbd52e1be67a1af2e SwiftGen: 4993cbf71cbc4886f775e26f8d5c3a1188ec9f99 SwiftLint: eb47480d47c982481592c195c221d11013a679cc - SwiftyMocky: c5e96e4ff76ec6dbf5a5941aeb039b5a546954a0 -PODFILE CHECKSUM: e8bbf406ccbac3957d776aa8c54be841a7924630 +PODFILE CHECKSUM: 31b8f7262ae9f13a758208949fd90392411de033 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/Profile/Mockfile b/Profile/Mockfile deleted file mode 100644 index 9d3f7e354..000000000 --- a/Profile/Mockfile +++ /dev/null @@ -1,18 +0,0 @@ -sourceryCommand: mint run krzysztofzablocki/Sourcery@2.1.2 sourcery -sourceryTemplate: ../MockTemplate.swifttemplate -unit.tests.mock: - sources: - include: - - ./../Core - - ./Profile - exclude: [] - output: ./ProfileTests/ProfileMock.generated.swift - targets: - - MyAppUnitTests - import: - - Core - - Profile - - Foundation - - SwiftUI - - Combine - - OEXFoundation \ No newline at end of file diff --git a/Profile/Profile.xcodeproj/project.pbxproj b/Profile/Profile.xcodeproj/project.pbxproj index 2112dc76f..a44199e1f 100644 --- a/Profile/Profile.xcodeproj/project.pbxproj +++ b/Profile/Profile.xcodeproj/project.pbxproj @@ -44,7 +44,6 @@ 02A4833329B7710A00D33F33 /* DeleteAccountViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A4833229B7710A00D33F33 /* DeleteAccountViewModelTests.swift */; }; 02A9A91D2978194A00B55797 /* ProfileViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A9A91C2978194A00B55797 /* ProfileViewModelTests.swift */; }; 02A9A91E2978194A00B55797 /* Profile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 020F834A28DB4CCD0062FA70 /* Profile.framework */; platformFilter = ios; }; - 02A9A92B29781A6300B55797 /* ProfileMock.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A9A92A29781A6300B55797 /* ProfileMock.generated.swift */; }; 02B089432A9F832200754BD4 /* ProfileStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B089422A9F832200754BD4 /* ProfileStorage.swift */; }; 02D0FD092AD698380020D752 /* UserProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D0FD082AD698380020D752 /* UserProfileView.swift */; }; 02D0FD0B2AD6984D0020D752 /* UserProfileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D0FD0A2AD6984D0020D752 /* UserProfileViewModel.swift */; }; @@ -59,6 +58,7 @@ 25B36FF48C1307888A3890DA /* Pods_App_Profile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BEA369C38362C1A91A012F70 /* Pods_App_Profile.framework */; }; BAD9CA3F2B29BF5C00DE790A /* ProfileSupportInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAD9CA3E2B29BF5C00DE790A /* ProfileSupportInfoView.swift */; }; CE1735042CD23D7A00F9606A /* DatesAndCalendarViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1735032CD23D7A00F9606A /* DatesAndCalendarViewModelTests.swift */; }; + CE73457329781A6300B55797 /* ProfileMocks.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE73457229781A6300B55797 /* ProfileMocks.generated.swift */; }; CE7CAF3D2CC1562C00E0AC9D /* OEXFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CE7CAF3C2CC1562C00E0AC9D /* OEXFoundation */; }; CE961F032CD163FD00799B9F /* CalendarManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE961F022CD163FD00799B9F /* CalendarManagerTests.swift */; }; CEB1E2702CC14EB000921517 /* OEXFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CEB1E26F2CC14EB000921517 /* OEXFoundation */; }; @@ -128,7 +128,6 @@ 02A4833229B7710A00D33F33 /* DeleteAccountViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DeleteAccountViewModelTests.swift; path = ProfileTests/Presentation/DeleteAccount/DeleteAccountViewModelTests.swift; sourceTree = SOURCE_ROOT; }; 02A9A91A2978194A00B55797 /* ProfileTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ProfileTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 02A9A91C2978194A00B55797 /* ProfileViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewModelTests.swift; sourceTree = ""; }; - 02A9A92A29781A6300B55797 /* ProfileMock.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileMock.generated.swift; sourceTree = ""; }; 02B089422A9F832200754BD4 /* ProfileStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileStorage.swift; sourceTree = ""; }; 02D0FD082AD698380020D752 /* UserProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileView.swift; sourceTree = ""; }; 02D0FD0A2AD6984D0020D752 /* UserProfileViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileViewModel.swift; sourceTree = ""; }; @@ -158,6 +157,7 @@ BEA369C38362C1A91A012F70 /* Pods_App_Profile.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App_Profile.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C85ADF87135E03275A980E07 /* Pods_App_Profile_ProfileTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App_Profile_ProfileTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CE1735032CD23D7A00F9606A /* DatesAndCalendarViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatesAndCalendarViewModelTests.swift; sourceTree = ""; }; + CE73457229781A6300B55797 /* ProfileMocks.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileMocks.generated.swift; sourceTree = ""; }; CE961F022CD163FD00799B9F /* CalendarManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarManagerTests.swift; sourceTree = ""; }; F52EFE7DC07BE68B9A302DAF /* Pods-App-Profile.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Profile.debug.xcconfig"; path = "Target Support Files/Pods-App-Profile/Pods-App-Profile.debug.xcconfig"; sourceTree = ""; }; FB33709D5DBACDEA33BD016F /* Pods-App-Profile-ProfileTests.debugstage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Profile-ProfileTests.debugstage.xcconfig"; path = "Target Support Files/Pods-App-Profile-ProfileTests/Pods-App-Profile-ProfileTests.debugstage.xcconfig"; sourceTree = ""; }; @@ -401,7 +401,7 @@ CE961F022CD163FD00799B9F /* CalendarManagerTests.swift */, CE1735032CD23D7A00F9606A /* DatesAndCalendarViewModelTests.swift */, 0766DFD3299AD9D800EBEF6A /* Presentation */, - 02A9A92A29781A6300B55797 /* ProfileMock.generated.swift */, + CE73457429781A6300B55797 /* Generated */, ); path = ProfileTests; sourceTree = ""; @@ -474,6 +474,14 @@ name = Frameworks; sourceTree = ""; }; + CE73457429781A6300B55797 /* Generated */ = { + isa = PBXGroup; + children = ( + CE73457229781A6300B55797 /* ProfileMocks.generated.swift */, + ); + path = Generated; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -515,7 +523,6 @@ 02A9A9162978194A00B55797 /* Sources */, 02A9A9172978194A00B55797 /* Frameworks */, 02A9A9182978194A00B55797 /* Resources */, - E4D48C711DA7F62E34A40309 /* [CP] Copy Pods Resources */, CE7CAF3F2CC1562C00E0AC9D /* Embed Frameworks */, ); buildRules = ( @@ -663,23 +670,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - E4D48C711DA7F62E34A40309 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Profile-ProfileTests/Pods-App-Profile-ProfileTests-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Profile-ProfileTests/Pods-App-Profile-ProfileTests-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App-Profile-ProfileTests/Pods-App-Profile-ProfileTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -735,7 +725,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 02A9A92B29781A6300B55797 /* ProfileMock.generated.swift in Sources */, + CE73457329781A6300B55797 /* ProfileMocks.generated.swift in Sources */, CE1735042CD23D7A00F9606A /* DatesAndCalendarViewModelTests.swift in Sources */, 02A4833329B7710A00D33F33 /* DeleteAccountViewModelTests.swift in Sources */, 02FE9A802BC707D500B3C206 /* SettingsViewModelTests.swift in Sources */, diff --git a/Profile/Profile/Data/Persistence/ProfilePersistenceProtocol.swift b/Profile/Profile/Data/Persistence/ProfilePersistenceProtocol.swift index a68940057..1e6d151cf 100644 --- a/Profile/Profile/Data/Persistence/ProfilePersistenceProtocol.swift +++ b/Profile/Profile/Data/Persistence/ProfilePersistenceProtocol.swift @@ -8,7 +8,7 @@ import CoreData import Core -//sourcery: AutoMockable +/// @mockable public protocol ProfilePersistenceProtocol: Sendable { func getCourseState(courseID: String) async -> CourseCalendarState? func getAllCourseStates() async -> [CourseCalendarState] @@ -22,7 +22,7 @@ public protocol ProfilePersistenceProtocol: Sendable { } #if DEBUG -public struct ProfilePersistenceMock: ProfilePersistenceProtocol { +public struct ProfilePersistencePreview: ProfilePersistenceProtocol { public func getCourseState(courseID: String) async -> CourseCalendarState? { nil } public func getAllCourseStates() async -> [CourseCalendarState] {[]} public func saveCourseState(state: CourseCalendarState) async {} diff --git a/Profile/Profile/Data/ProfileStorage.swift b/Profile/Profile/Data/ProfileStorage.swift index cf1eb9294..3f69b1dd6 100644 --- a/Profile/Profile/Data/ProfileStorage.swift +++ b/Profile/Profile/Data/ProfileStorage.swift @@ -9,7 +9,7 @@ import Foundation import Core import UIKit -//sourcery: AutoMockable +/// @mockable public protocol ProfileStorage: Sendable { var userProfile: DataLayer.UserProfile? {get set} var useRelativeDates: Bool {get set} @@ -22,7 +22,7 @@ public protocol ProfileStorage: Sendable { } #if DEBUG -public final class ProfileStorageMock: ProfileStorage, @unchecked Sendable { +public final class ProfileStoragePreview: ProfileStorage, @unchecked Sendable { public var useRelativeDates: Bool = true public var userProfile: DataLayer.UserProfile? public var calendarSettings: CalendarSettings? diff --git a/Profile/Profile/Domain/ProfileInteractor.swift b/Profile/Profile/Domain/ProfileInteractor.swift index e1813637d..e0d1cb8c2 100644 --- a/Profile/Profile/Domain/ProfileInteractor.swift +++ b/Profile/Profile/Domain/ProfileInteractor.swift @@ -9,7 +9,7 @@ import Foundation import Core import UIKit -//sourcery: AutoMockable +/// @mockable public protocol ProfileInteractorProtocol: Sendable { func getUserProfile(username: String) async throws -> UserProfile func getMyProfile() async throws -> UserProfile diff --git a/Profile/Profile/Presentation/DatesAndCalendar/CoursesToSyncView.swift b/Profile/Profile/Presentation/DatesAndCalendar/CoursesToSyncView.swift index f1aae91ef..362a1f27e 100644 --- a/Profile/Profile/Presentation/DatesAndCalendar/CoursesToSyncView.swift +++ b/Profile/Profile/Presentation/DatesAndCalendar/CoursesToSyncView.swift @@ -153,10 +153,10 @@ public struct CoursesToSyncView: View { struct CoursesToSyncView_Previews: PreviewProvider { static var previews: some View { let vm = DatesAndCalendarViewModel( - router: ProfileRouterMock(), + router: ProfileRouterPreview(), interactor: ProfileInteractor(repository: ProfileRepositoryMock()), - profileStorage: ProfileStorageMock(), - persistence: ProfilePersistenceMock(), + profileStorage: ProfileStoragePreview(), + persistence: ProfilePersistencePreview(), calendarManager: CalendarManagerMock(), connectivity: Connectivity(config: ConfigMock()) ) diff --git a/Profile/Profile/Presentation/DatesAndCalendar/DatesAndCalendarView.swift b/Profile/Profile/Presentation/DatesAndCalendar/DatesAndCalendarView.swift index 6539ea081..671c1f2b9 100644 --- a/Profile/Profile/Presentation/DatesAndCalendar/DatesAndCalendarView.swift +++ b/Profile/Profile/Presentation/DatesAndCalendar/DatesAndCalendarView.swift @@ -183,10 +183,10 @@ public struct DatesAndCalendarView: View { struct DatesAndCalendarView_Previews: PreviewProvider { static var previews: some View { let vm = DatesAndCalendarViewModel( - router: ProfileRouterMock(), + router: ProfileRouterPreview(), interactor: ProfileInteractor(repository: ProfileRepositoryMock()), - profileStorage: ProfileStorageMock(), - persistence: ProfilePersistenceMock(), + profileStorage: ProfileStoragePreview(), + persistence: ProfilePersistencePreview(), calendarManager: CalendarManagerMock(), connectivity: Connectivity(config: ConfigMock()) ) diff --git a/Profile/Profile/Presentation/DatesAndCalendar/Elements/NewCalendarView.swift b/Profile/Profile/Presentation/DatesAndCalendar/Elements/NewCalendarView.swift index ed4e27b8a..cff53dde2 100644 --- a/Profile/Profile/Presentation/DatesAndCalendar/Elements/NewCalendarView.swift +++ b/Profile/Profile/Presentation/DatesAndCalendar/Elements/NewCalendarView.swift @@ -160,12 +160,12 @@ struct NewCalendarView: View { NewCalendarView( title: .changeSyncOptions, viewModel: DatesAndCalendarViewModel( - router: ProfileRouterMock(), + router: ProfileRouterPreview(), interactor: ProfileInteractor( repository: ProfileRepositoryMock() ), - profileStorage: ProfileStorageMock(), - persistence: ProfilePersistenceMock(), + profileStorage: ProfileStoragePreview(), + persistence: ProfilePersistencePreview(), calendarManager: CalendarManagerMock(), connectivity: Connectivity(config: ConfigMock()) ), diff --git a/Profile/Profile/Presentation/DatesAndCalendar/SyncCalendarOptionsView.swift b/Profile/Profile/Presentation/DatesAndCalendar/SyncCalendarOptionsView.swift index be28cc458..2be3eeb38 100644 --- a/Profile/Profile/Presentation/DatesAndCalendar/SyncCalendarOptionsView.swift +++ b/Profile/Profile/Presentation/DatesAndCalendar/SyncCalendarOptionsView.swift @@ -266,10 +266,10 @@ public struct SyncCalendarOptionsView: View { struct SyncCalendarOptionsView_Previews: PreviewProvider { static var previews: some View { let vm = DatesAndCalendarViewModel( - router: ProfileRouterMock(), + router: ProfileRouterPreview(), interactor: ProfileInteractor(repository: ProfileRepositoryMock()), - profileStorage: ProfileStorageMock(), - persistence: ProfilePersistenceMock(), + profileStorage: ProfileStoragePreview(), + persistence: ProfilePersistencePreview(), calendarManager: CalendarManagerMock(), connectivity: Connectivity(config: ConfigMock()) ) diff --git a/Profile/Profile/Presentation/DeleteAccount/DeleteAccountView.swift b/Profile/Profile/Presentation/DeleteAccount/DeleteAccountView.swift index 9b2ad9525..2e2d30c3d 100644 --- a/Profile/Profile/Presentation/DeleteAccount/DeleteAccountView.swift +++ b/Profile/Profile/Presentation/DeleteAccount/DeleteAccountView.swift @@ -184,12 +184,12 @@ public struct DeleteAccountView: View { #if DEBUG struct DeleteAccountView_Previews: PreviewProvider { static var previews: some View { - let router = ProfileRouterMock() + let router = ProfileRouterPreview() let vm = DeleteAccountViewModel( interactor: ProfileInteractor.mock, router: router, connectivity: Connectivity(config: ConfigMock()), - analytics: ProfileAnalyticsMock() + analytics: ProfileAnalyticsPreview() ) DeleteAccountView(viewModel: vm) diff --git a/Profile/Profile/Presentation/EditProfile/EditProfileView.swift b/Profile/Profile/Presentation/EditProfile/EditProfileView.swift index e82df4e6a..cfe8f2d66 100644 --- a/Profile/Profile/Presentation/EditProfile/EditProfileView.swift +++ b/Profile/Profile/Presentation/EditProfile/EditProfileView.swift @@ -275,8 +275,8 @@ struct EditProfileView_Previews: PreviewProvider { viewModel: EditProfileViewModel( userModel: userModel, interactor: ProfileInteractor.mock, - router: ProfileRouterMock(), - analytics: ProfileAnalyticsMock()), + router: ProfileRouterPreview(), + analytics: ProfileAnalyticsPreview()), avatar: nil, profileDidEdit: {_ in} ) diff --git a/Profile/Profile/Presentation/Profile/ProfileView.swift b/Profile/Profile/Presentation/Profile/ProfileView.swift index b1c2e6c6d..6ff685b80 100644 --- a/Profile/Profile/Presentation/Profile/ProfileView.swift +++ b/Profile/Profile/Presentation/Profile/ProfileView.swift @@ -188,12 +188,12 @@ public struct ProfileView: View { #if DEBUG struct ProfileView_Previews: PreviewProvider { static var previews: some View { - let router = ProfileRouterMock() + let router = ProfileRouterPreview() let config = ConfigMock() let vm = ProfileViewModel( interactor: ProfileInteractor.mock, router: router, - analytics: ProfileAnalyticsMock(), + analytics: ProfileAnalyticsPreview(), config: config, connectivity: Connectivity(config: config) ) diff --git a/Profile/Profile/Presentation/ProfileAnalytics.swift b/Profile/Profile/Presentation/ProfileAnalytics.swift index 2f59ddf3a..8104dc0be 100644 --- a/Profile/Profile/Presentation/ProfileAnalytics.swift +++ b/Profile/Profile/Presentation/ProfileAnalytics.swift @@ -9,7 +9,7 @@ import Foundation import Core import OEXFoundation -//sourcery: AutoMockable +/// @mockable public protocol ProfileAnalytics { func profileEditClicked() func profileSwitch(action: String) @@ -31,7 +31,7 @@ public protocol ProfileAnalytics { } #if DEBUG -class ProfileAnalyticsMock: ProfileAnalytics { +class ProfileAnalyticsPreview: ProfileAnalytics { public func profileEditClicked() {} public func profileSwitch(action: String) {} public func profileEditDoneClicked() {} diff --git a/Profile/Profile/Presentation/ProfileRouter.swift b/Profile/Profile/Presentation/ProfileRouter.swift index 246e0cdf1..b87a24ca9 100644 --- a/Profile/Profile/Presentation/ProfileRouter.swift +++ b/Profile/Profile/Presentation/ProfileRouter.swift @@ -9,7 +9,7 @@ import Foundation import Core import UIKit -//sourcery: AutoMockable +/// @mockable @MainActor public protocol ProfileRouter: BaseRouter { @@ -45,7 +45,7 @@ public protocol ProfileRouter: BaseRouter { // Mark - For testing and SwiftUI preview #if DEBUG -public class ProfileRouterMock: BaseRouterMock, ProfileRouter { +public class ProfileRouterPreview: BaseRouterMock, ProfileRouter { public override init() {} diff --git a/Profile/Profile/Presentation/Settings/ManageAccountView.swift b/Profile/Profile/Presentation/Settings/ManageAccountView.swift index 154eddbcf..a7b79625c 100644 --- a/Profile/Profile/Presentation/Settings/ManageAccountView.swift +++ b/Profile/Profile/Presentation/Settings/ManageAccountView.swift @@ -200,12 +200,12 @@ public struct ManageAccountView: View { #if DEBUG struct ManageAccountView_Previews: PreviewProvider { static var previews: some View { - let router = ProfileRouterMock() + let router = ProfileRouterPreview() let configMock = ConfigMock() let vm = ManageAccountViewModel( router: router, - analytics: ProfileAnalyticsMock(), + analytics: ProfileAnalyticsPreview(), config: configMock, connectivity: Connectivity(config: configMock), interactor: ProfileInteractor.mock diff --git a/Profile/Profile/Presentation/Settings/SettingsView.swift b/Profile/Profile/Presentation/Settings/SettingsView.swift index b1410b656..2304686e0 100644 --- a/Profile/Profile/Presentation/Settings/SettingsView.swift +++ b/Profile/Profile/Presentation/Settings/SettingsView.swift @@ -245,12 +245,12 @@ public struct SettingsView: View { #if DEBUG #Preview { - let router = ProfileRouterMock() + let router = ProfileRouterPreview() let vm = SettingsViewModel( interactor: ProfileInteractor.mock, downloadManager: DownloadManagerMock(), router: router, - analytics: ProfileAnalyticsMock(), + analytics: ProfileAnalyticsPreview(), coreAnalytics: CoreAnalyticsMock(), config: ConfigMock(), corePersistence: CorePersistenceMock(), diff --git a/Profile/Profile/Presentation/Settings/VideoQualityView.swift b/Profile/Profile/Presentation/Settings/VideoQualityView.swift index 8f662976d..abcf5da33 100644 --- a/Profile/Profile/Presentation/Settings/VideoQualityView.swift +++ b/Profile/Profile/Presentation/Settings/VideoQualityView.swift @@ -125,12 +125,12 @@ public struct VideoQualityView: View { #if DEBUG #Preview { - let router = ProfileRouterMock() + let router = ProfileRouterPreview() let vm = SettingsViewModel( interactor: ProfileInteractor.mock, downloadManager: DownloadManagerMock(), router: router, - analytics: ProfileAnalyticsMock(), + analytics: ProfileAnalyticsPreview(), coreAnalytics: CoreAnalyticsMock(), config: ConfigMock(), corePersistence: CorePersistenceMock(), diff --git a/Profile/Profile/Presentation/Settings/VideoSettingsView.swift b/Profile/Profile/Presentation/Settings/VideoSettingsView.swift index a8c29bcc0..bc05ba3fb 100644 --- a/Profile/Profile/Presentation/Settings/VideoSettingsView.swift +++ b/Profile/Profile/Presentation/Settings/VideoSettingsView.swift @@ -132,12 +132,12 @@ public struct VideoSettingsView: View { #if DEBUG #Preview { - let router = ProfileRouterMock() + let router = ProfileRouterPreview() let vm = SettingsViewModel( interactor: ProfileInteractor.mock, downloadManager: DownloadManagerMock(), router: router, - analytics: ProfileAnalyticsMock(), + analytics: ProfileAnalyticsPreview(), coreAnalytics: CoreAnalyticsMock(), config: ConfigMock(), corePersistence: CorePersistenceMock(), diff --git a/Profile/ProfileTests/CalendarManagerTests.swift b/Profile/ProfileTests/CalendarManagerTests.swift index db9454d0f..4e3db38ef 100644 --- a/Profile/ProfileTests/CalendarManagerTests.swift +++ b/Profile/ProfileTests/CalendarManagerTests.swift @@ -6,7 +6,6 @@ // -import SwiftyMocky import XCTest import EventKit @testable import Profile @@ -16,92 +15,96 @@ import SwiftUI @MainActor final class CalendarManagerTests: XCTestCase { - + func testCourseStatusSynced() async { let persistence = ProfilePersistenceProtocolMock() let interactor = ProfileInteractorProtocolMock() let profileStorage = ProfileStorageMock() - + let manager = CalendarManager( persistence: persistence, interactor: interactor, profileStorage: profileStorage ) - + let states = [CourseCalendarState(courseID: "course-1", checksum: "checksum-1")] - Given(persistence, .getAllCourseStates(willReturn: states)) - + persistence.getAllCourseStatesHandler = { states } + let status = await manager.courseStatus(courseID: "course-1") - - Verify(persistence, 1, .getAllCourseStates()) + + XCTAssertEqual(persistence.getAllCourseStatesCallCount, 1) XCTAssertEqual(status, .synced) } - + func testCourseStatusOffline() async { let persistence = ProfilePersistenceProtocolMock() let interactor = ProfileInteractorProtocolMock() let profileStorage = ProfileStorageMock() - + let manager = CalendarManager( persistence: persistence, interactor: interactor, profileStorage: profileStorage ) - + let states = [CourseCalendarState(courseID: "course-2", checksum: "checksum-2")] - Given(persistence, .getAllCourseStates(willReturn: states)) - + persistence.getAllCourseStatesHandler = { states } + let status = await manager.courseStatus(courseID: "course-1") - - Verify(persistence, 1, .getAllCourseStates()) + + XCTAssertEqual(persistence.getAllCourseStatesCallCount, 1) XCTAssertEqual(status, .offline) } - + func testIsDatesChanged() async { let persistence = ProfilePersistenceProtocolMock() let interactor = ProfileInteractorProtocolMock() let profileStorage = ProfileStorageMock() - + let manager = CalendarManager( persistence: persistence, interactor: interactor, profileStorage: profileStorage ) - + let state = CourseCalendarState(courseID: "course-1", checksum: "old-checksum") - Given(persistence, .getCourseState(courseID: .value("course-1"), willReturn: state)) - + persistence.getCourseStateHandler = { courseID in + return courseID == "course-1" ? state : nil + } + let changed = await manager.isDatesChanged(courseID: "course-1", checksum: "new-checksum") - - Verify(persistence, 1, .getCourseState(courseID: .value("course-1"))) + + XCTAssertEqual(persistence.getCourseStateCallCount, 1) XCTAssertTrue(changed) } - + func testIsDatesNotChanged() async { let persistence = ProfilePersistenceProtocolMock() let interactor = ProfileInteractorProtocolMock() let profileStorage = ProfileStorageMock() - + let manager = CalendarManager( persistence: persistence, interactor: interactor, profileStorage: profileStorage ) - + let state = CourseCalendarState(courseID: "course-1", checksum: "same-checksum") - Given(persistence, .getCourseState(courseID: .value("course-1"), willReturn: state)) - + persistence.getCourseStateHandler = { courseID in + return courseID == "course-1" ? state : nil + } + let changed = await manager.isDatesChanged(courseID: "course-1", checksum: "same-checksum") - - Verify(persistence, 1, .getCourseState(courseID: .value("course-1"))) + + XCTAssertEqual(persistence.getCourseStateCallCount, 1) XCTAssertFalse(changed) } - + func testClearAllData() async { let persistence = ProfilePersistenceProtocolMock() let interactor = ProfileInteractorProtocolMock() let profileStorage = ProfileStorageMock() - + // Setup initial values profileStorage.firstCalendarUpdate = true profileStorage.hideInactiveCourses = true @@ -113,25 +116,27 @@ final class CalendarManagerTests: XCTestCase { courseCalendarSync: true ) profileStorage.lastCalendarUpdateDate = Date() - + // Verify initial values are set XCTAssertTrue(profileStorage.firstCalendarUpdate ?? false) XCTAssertTrue(profileStorage.hideInactiveCourses ?? false) XCTAssertNotNil(profileStorage.lastCalendarName) XCTAssertNotNil(profileStorage.calendarSettings) XCTAssertNotNil(profileStorage.lastCalendarUpdateDate) - + let manager = CalendarManager( persistence: persistence, interactor: interactor, profileStorage: profileStorage ) - + + persistence.deleteAllCourseStatesAndEventsHandler = { } + await manager.clearAllData(removeCalendar: true) - + // Verify persistence method was called - Verify(persistence, 1, .deleteAllCourseStatesAndEvents()) - + XCTAssertEqual(persistence.deleteAllCourseStatesAndEventsCallCount, 1) + // Verify all values were cleared XCTAssertEqual(profileStorage.firstCalendarUpdate, false) XCTAssertNil(profileStorage.hideInactiveCourses) @@ -139,89 +144,86 @@ final class CalendarManagerTests: XCTestCase { XCTAssertNil(profileStorage.calendarSettings) XCTAssertNil(profileStorage.lastCalendarUpdateDate) } - + func testFilterCoursesBySelected() async throws { - let persistence = ProfilePersistenceProtocolMock() - let interactor = ProfileInteractorProtocolMock() - let profileStorage = ProfileStorageMock() - - let manager = CalendarManager( - persistence: persistence, - interactor: interactor, - profileStorage: profileStorage + let persistence = ProfilePersistenceProtocolMock() + let interactor = ProfileInteractorProtocolMock() + let profileStorage = ProfileStorageMock() + + let manager = CalendarManager( + persistence: persistence, + interactor: interactor, + profileStorage: profileStorage + ) + + let states = [ + CourseCalendarState(courseID: "course-1", checksum: "checksum-1"), + CourseCalendarState(courseID: "course-2", checksum: "checksum-2"), + CourseCalendarState(courseID: "course-3", checksum: "checksum-3") + ] + + let fetchedCourses = [ + CourseForSync( + id: UUID(), + courseID: "course-1", + name: "Course 1", + synced: true, + recentlyActive: true + ), + CourseForSync( + id: UUID(), + courseID: "course-2", + name: "Course 2", + synced: true, + recentlyActive: false + ), + CourseForSync( + id: UUID(), + courseID: "course-4", + name: "Course 4", + synced: false, + recentlyActive: true ) - - let states = [ - CourseCalendarState(courseID: "course-1", checksum: "checksum-1"), - CourseCalendarState(courseID: "course-2", checksum: "checksum-2"), - CourseCalendarState(courseID: "course-3", checksum: "checksum-3") - ] - - let fetchedCourses = [ - CourseForSync( - id: UUID(), - courseID: "course-1", - name: "Course 1", - synced: true, - recentlyActive: true - ), - CourseForSync( - id: UUID(), - courseID: "course-2", - name: "Course 2", - synced: true, - recentlyActive: false - ), - CourseForSync( - id: UUID(), - courseID: "course-4", - name: "Course 4", - synced: false, - recentlyActive: true - ) - ] - - // Setup mocks - Given(persistence, .getAllCourseStates(willReturn: states)) - Given(persistence, .getCourseCalendarEvents(for: .any, willReturn: [])) - Given(persistence, .getCourseState(courseID: .any, willReturn: nil)) -// Given(persistence, .removeCourseCalendarEvents(for: .any, willProduce: { _ in })) - - // Execute filtering - let filteredCourses = await manager.filterCoursesBySelected(fetchedCourses: fetchedCourses) - - // Verify calls - Verify(persistence, 1, .getAllCourseStates()) - - // Verify course-3 was removed (exists in states but not in fetched) - Verify(persistence, 1, .getCourseCalendarEvents(for: .value("course-3"))) - Verify(persistence, 1, .removeCourseCalendarEvents(for: .value("course-3"))) - - // Verify course-2 was removed (inactive) - Verify(persistence, 1, .getCourseCalendarEvents(for: .value("course-2"))) - Verify(persistence, 1, .removeCourseCalendarEvents(for: .value("course-2"))) - - // Verify results - XCTAssertEqual(filteredCourses.count, 1) - XCTAssertEqual(filteredCourses.first?.courseID, "course-1") - XCTAssertEqual(filteredCourses.first?.name, "Course 1") - XCTAssertTrue(filteredCourses.first?.synced ?? false) - XCTAssertTrue(filteredCourses.first?.recentlyActive ?? false) - } - + ] + + // Setup mocks + persistence.getAllCourseStatesHandler = { states } + persistence.getCourseCalendarEventsHandler = { _ in [] } + persistence.getCourseStateHandler = { _ in nil } + persistence.removeCourseCalendarEventsHandler = { _ in } + persistence.saveCourseStateHandler = { _ in } + + // Execute filtering + let filteredCourses = await manager.filterCoursesBySelected(fetchedCourses: fetchedCourses) + + // Verify calls + XCTAssertEqual(persistence.getAllCourseStatesCallCount, 1) + + // Verify course-3 was removed (exists in states but not in fetched) + XCTAssertGreaterThanOrEqual(persistence.getCourseCalendarEventsCallCount, 1) + XCTAssertGreaterThanOrEqual(persistence.removeCourseCalendarEventsCallCount, 1) + + // Verify results + XCTAssertEqual(filteredCourses.count, 1) + XCTAssertEqual(filteredCourses.first?.courseID, "course-1") + XCTAssertEqual(filteredCourses.first?.name, "Course 1") + XCTAssertTrue(filteredCourses.first?.synced ?? false) + XCTAssertTrue(filteredCourses.first?.recentlyActive ?? false) + } + func testFilterCoursesBySelectedEmptyStates() async { let persistence = ProfilePersistenceProtocolMock() let interactor = ProfileInteractorProtocolMock() let profileStorage = ProfileStorageMock() - + let manager = CalendarManager( persistence: persistence, interactor: interactor, profileStorage: profileStorage ) - - Given(persistence, .getAllCourseStates(willReturn: [])) - + + persistence.getAllCourseStatesHandler = { [] } + let fetchedCourses = [ CourseForSync( id: UUID(), @@ -238,54 +240,54 @@ final class CalendarManagerTests: XCTestCase { recentlyActive: false ) ] - + let filteredCourses = await manager.filterCoursesBySelected(fetchedCourses: fetchedCourses) - - Verify(persistence, 1, .getAllCourseStates()) + + XCTAssertEqual(persistence.getAllCourseStatesCallCount, 1) XCTAssertEqual(filteredCourses, fetchedCourses) } - + func testCalendarNameFromSettings() { let persistence = ProfilePersistenceProtocolMock() let interactor = ProfileInteractorProtocolMock() let profileStorage = ProfileStorageMock() - + let settings = CalendarSettings( colorSelection: "accent", calendarName: "Test Calendar", accountSelection: "iCloud", courseCalendarSync: true ) - Given(profileStorage, .calendarSettings(getter: settings)) - + profileStorage.calendarSettings = settings + let manager = CalendarManager( persistence: persistence, interactor: interactor, profileStorage: profileStorage ) - + XCTAssertEqual(manager.calendarName, "Test Calendar") } - + func testColorSelectionFromSettings() { let persistence = ProfilePersistenceProtocolMock() let interactor = ProfileInteractorProtocolMock() let profileStorage = ProfileStorageMock() - + let settings = CalendarSettings( colorSelection: "accent", calendarName: "Test Calendar", accountSelection: "iCloud", courseCalendarSync: true ) - Given(profileStorage, .calendarSettings(getter: settings)) - + profileStorage.calendarSettings = settings + let manager = CalendarManager( persistence: persistence, interactor: interactor, profileStorage: profileStorage ) - + XCTAssertEqual(manager.colorSelection?.color, Color.accentColor) } } diff --git a/Profile/ProfileTests/DatesAndCalendarViewModelTests.swift b/Profile/ProfileTests/DatesAndCalendarViewModelTests.swift index 5950ca17c..cfd08acf4 100644 --- a/Profile/ProfileTests/DatesAndCalendarViewModelTests.swift +++ b/Profile/ProfileTests/DatesAndCalendarViewModelTests.swift @@ -5,8 +5,6 @@ // Created by Ivan Stepanok on 30.10.2024. // - -import SwiftyMocky import XCTest import EventKit @testable import Profile @@ -17,14 +15,14 @@ import Combine @MainActor final class DatesAndCalendarViewModelTests: XCTestCase { - + var cancellables: Set! - + override func setUp() { super.setUp() cancellables = [] } - + func testLoadCalendarOptions() { // Given let router = ProfileRouterMock() @@ -33,17 +31,17 @@ final class DatesAndCalendarViewModelTests: XCTestCase { let calendarManager = CalendarManagerProtocolMock() let connectivity = ConnectivityProtocolMock() let profileStorage = ProfileStorageMock() - + let settings = CalendarSettings( colorSelection: "accent", calendarName: "Test Calendar", accountSelection: "iCloud", courseCalendarSync: true ) - Given(profileStorage, .calendarSettings(getter: settings)) - Given(profileStorage, .lastCalendarName(getter: "Old Calendar")) - Given(profileStorage, .hideInactiveCourses(getter: true)) - + profileStorage.calendarSettings = settings + profileStorage.lastCalendarName = "Old Calendar" + profileStorage.hideInactiveCourses = true + let viewModel = DatesAndCalendarViewModel( router: router, interactor: interactor, @@ -52,10 +50,10 @@ final class DatesAndCalendarViewModelTests: XCTestCase { calendarManager: calendarManager, connectivity: connectivity ) - + // When viewModel.loadCalendarOptions() - + // Then XCTAssertEqual(viewModel.colorSelection?.colorString, "accent") XCTAssertEqual(viewModel.accountSelection?.title, "iCloud") @@ -64,7 +62,7 @@ final class DatesAndCalendarViewModelTests: XCTestCase { XCTAssertTrue(viewModel.courseCalendarSync) XCTAssertTrue(viewModel.hideInactiveCourses) } - + func testClearAllData() async { // Given let router = ProfileRouterMock() @@ -73,7 +71,11 @@ final class DatesAndCalendarViewModelTests: XCTestCase { let calendarManager = CalendarManagerProtocolMock() let connectivity = ConnectivityProtocolMock() let profileStorage = ProfileStorageMock() - + + calendarManager.clearAllDataHandler = { _ in } + router.backHandler = { _ in } + router.showDatesAndCalendarHandler = { } + let viewModel = DatesAndCalendarViewModel( router: router, interactor: interactor, @@ -82,19 +84,19 @@ final class DatesAndCalendarViewModelTests: XCTestCase { calendarManager: calendarManager, connectivity: connectivity ) - + // When await viewModel.clearAllData() - + // Then - Verify(calendarManager, 1, .clearAllData(removeCalendar: .value(true))) - Verify(router, 1, .back(animated: .value(false))) - Verify(router, 1, .showDatesAndCalendar()) + XCTAssertEqual(calendarManager.clearAllDataCallCount, 1) + XCTAssertEqual(router.backCallCount, 1) + XCTAssertEqual(router.showDatesAndCalendarCallCount, 1) XCTAssertTrue(viewModel.courseCalendarSync) XCTAssertFalse(viewModel.showDisableCalendarSync) XCTAssertFalse(viewModel.openNewCalendarView) } - + func testSaveCalendarOptions() { // Given let router = ProfileRouterMock() @@ -103,15 +105,15 @@ final class DatesAndCalendarViewModelTests: XCTestCase { let calendarManager = CalendarManagerProtocolMock() let connectivity = ConnectivityProtocolMock() let profileStorage = ProfileStorageMock() - - var settings = CalendarSettings( + + let settings = CalendarSettings( colorSelection: "accent", calendarName: "Old Calendar", accountSelection: "iCloud", courseCalendarSync: true ) - Given(profileStorage, .calendarSettings(getter: settings)) - + profileStorage.calendarSettings = settings + let viewModel = DatesAndCalendarViewModel( router: router, interactor: interactor, @@ -120,14 +122,14 @@ final class DatesAndCalendarViewModelTests: XCTestCase { calendarManager: calendarManager, connectivity: connectivity ) - + // When viewModel.calendarName = "New Calendar" viewModel.colorSelection = .init(color: .red) viewModel.accountSelection = .init(title: "Local") viewModel.courseCalendarSync = false viewModel.saveCalendarOptions() - + // Then XCTAssertEqual(profileStorage.calendarSettings?.calendarName, "New Calendar") XCTAssertEqual(profileStorage.calendarSettings?.colorSelection, "red") @@ -135,7 +137,7 @@ final class DatesAndCalendarViewModelTests: XCTestCase { XCTAssertFalse(profileStorage.calendarSettings?.courseCalendarSync ?? true) XCTAssertEqual(profileStorage.lastCalendarName, "New Calendar") } - + func testFetchCoursesSuccess() async { // Given let router = ProfileRouterMock() @@ -144,10 +146,12 @@ final class DatesAndCalendarViewModelTests: XCTestCase { let calendarManager = CalendarManagerProtocolMock() let connectivity = ConnectivityProtocolMock() let profileStorage = ProfileStorageMock() - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(calendarManager, .requestAccess(willReturn: true)) - + + connectivity.isInternetAvaliable = true + calendarManager.requestAccessHandler = { true } + calendarManager.createCalendarIfNeededHandler = { } + calendarManager.filterCoursesBySelectedHandler = { $0 } + let courses = [ CourseForSync( id: UUID(), @@ -157,9 +161,9 @@ final class DatesAndCalendarViewModelTests: XCTestCase { recentlyActive: true ) ] - Given(interactor, .enrollmentsStatus(willReturn: courses)) - Given(persistence, .getAllCourseStates(willReturn: [])) - + interactor.enrollmentsStatusHandler = { courses } + persistence.getAllCourseStatesHandler = { [] } + let viewModel = DatesAndCalendarViewModel( router: router, interactor: interactor, @@ -168,18 +172,18 @@ final class DatesAndCalendarViewModelTests: XCTestCase { calendarManager: calendarManager, connectivity: connectivity ) - + // When await viewModel.fetchCourses() - + // Then XCTAssertEqual(viewModel.assignmentStatus, .synced) XCTAssertEqual(viewModel.coursesForSync.count, 1) XCTAssertEqual(viewModel.coursesForSync.first?.courseID, "course-1") - Verify(calendarManager, 1, .createCalendarIfNeeded()) - Verify(interactor, 1, .enrollmentsStatus()) + XCTAssertEqual(calendarManager.createCalendarIfNeededCallCount, 1) + XCTAssertEqual(interactor.enrollmentsStatusCallCount, 1) } - + func testRequestCalendarPermissionSuccess() async { // Given let router = ProfileRouterMock() @@ -188,9 +192,9 @@ final class DatesAndCalendarViewModelTests: XCTestCase { let calendarManager = CalendarManagerProtocolMock() let connectivity = ConnectivityProtocolMock() let profileStorage = ProfileStorageMock() - - Given(calendarManager, .requestAccess(willReturn: true)) - + + calendarManager.requestAccessHandler = { true } + let viewModel = DatesAndCalendarViewModel( router: router, interactor: interactor, @@ -199,15 +203,15 @@ final class DatesAndCalendarViewModelTests: XCTestCase { calendarManager: calendarManager, connectivity: connectivity ) - + // When await viewModel.requestCalendarPermission() - + // Then XCTAssertTrue(viewModel.openNewCalendarView) XCTAssertFalse(viewModel.showCalendaAccessDenied) } - + func testRequestCalendarPermissionDenied() async { // Given let router = ProfileRouterMock() @@ -216,9 +220,9 @@ final class DatesAndCalendarViewModelTests: XCTestCase { let calendarManager = CalendarManagerProtocolMock() let connectivity = ConnectivityProtocolMock() let profileStorage = ProfileStorageMock() - - Given(calendarManager, .requestAccess(willReturn: false)) - + + calendarManager.requestAccessHandler = { false } + let viewModel = DatesAndCalendarViewModel( router: router, interactor: interactor, @@ -227,15 +231,15 @@ final class DatesAndCalendarViewModelTests: XCTestCase { calendarManager: calendarManager, connectivity: connectivity ) - + // When await viewModel.requestCalendarPermission() - + // Then XCTAssertTrue(viewModel.showCalendaAccessDenied) XCTAssertFalse(viewModel.openNewCalendarView) } - + func testToggleSyncForCourse() { // Given let router = ProfileRouterMock() @@ -244,7 +248,7 @@ final class DatesAndCalendarViewModelTests: XCTestCase { let calendarManager = CalendarManagerProtocolMock() let connectivity = ConnectivityProtocolMock() let profileStorage = ProfileStorageMock() - + let course = CourseForSync( id: UUID(), courseID: "course-1", @@ -252,7 +256,7 @@ final class DatesAndCalendarViewModelTests: XCTestCase { synced: false, recentlyActive: true ) - + let viewModel = DatesAndCalendarViewModel( router: router, interactor: interactor, @@ -262,16 +266,16 @@ final class DatesAndCalendarViewModelTests: XCTestCase { connectivity: connectivity ) viewModel.coursesForSync = [course] - + // When viewModel.toggleSync(for: course) - + // Then XCTAssertTrue(viewModel.coursesForSync.first?.synced ?? false) XCTAssertEqual(viewModel.coursesForAdding.count, 1) XCTAssertEqual(viewModel.coursesForAdding.first?.courseID, "course-1") } - + func testDeleteOldCalendarIfNeeded() async { // Given let router = ProfileRouterMock() @@ -280,24 +284,26 @@ final class DatesAndCalendarViewModelTests: XCTestCase { let calendarManager = CalendarManagerProtocolMock() let connectivity = ConnectivityProtocolMock() let profileStorage = ProfileStorageMock() - + let settings = CalendarSettings( colorSelection: "accent", calendarName: "Old Calendar", accountSelection: "iCloud", courseCalendarSync: true ) - + let states = [ CourseCalendarState(courseID: "123", checksum: "checksum"), CourseCalendarState(courseID: "124", checksum: "checksum2") ] - - Given(persistence, .getAllCourseStates(willReturn: states)) - Given(profileStorage, .calendarSettings(getter: settings)) - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(calendarManager, .requestAccess(willReturn: true)) - + + persistence.getAllCourseStatesHandler = { states } + profileStorage.calendarSettings = settings + connectivity.isInternetAvaliable = true + calendarManager.requestAccessHandler = { true } + calendarManager.removeOldCalendarHandler = { } + persistence.removeAllCourseCalendarEventsHandler = { } + let courses = [ CourseForSync( id: UUID(), @@ -307,8 +313,8 @@ final class DatesAndCalendarViewModelTests: XCTestCase { recentlyActive: true ) ] - Given(interactor, .enrollmentsStatus(willReturn: courses)) - + interactor.enrollmentsStatusHandler = { courses } + let viewModel = DatesAndCalendarViewModel( router: router, interactor: interactor, @@ -318,12 +324,12 @@ final class DatesAndCalendarViewModelTests: XCTestCase { connectivity: connectivity ) viewModel.calendarName = "New Calendar" - + // When await viewModel.deleteOldCalendarIfNeeded() - + // Then - Verify(calendarManager, 1, .removeOldCalendar()) - Verify(persistence, 1, .removeAllCourseCalendarEvents()) + XCTAssertEqual(calendarManager.removeOldCalendarCallCount, 1) + XCTAssertEqual(persistence.removeAllCourseCalendarEventsCallCount, 1) } } diff --git a/Profile/ProfileTests/Generated/ProfileMocks.generated.swift b/Profile/ProfileTests/Generated/ProfileMocks.generated.swift new file mode 100644 index 000000000..52fa772a7 --- /dev/null +++ b/Profile/ProfileTests/Generated/ProfileMocks.generated.swift @@ -0,0 +1,2985 @@ +/// +/// @Generated by Mockolo +/// + + + +import Alamofire +import Combine +@testable import Core +import CoreData +import Foundation +import OEXFoundation +@testable import Profile +import SwiftUI +import UIKit +import ZipArchive + + +public final class ConfigProtocolMock: ConfigProtocol, @unchecked Sendable { + public init() { } + public init(baseURL: URL = URL(fileURLWithPath: ""), baseSSOURL: URL = URL(fileURLWithPath: ""), ssoFinishedURL: URL = URL(fileURLWithPath: ""), ssoButtonTitle: [String: Any] = [String: Any](), oAuthClientId: String = "", tokenType: TokenType, feedbackEmail: String = "", appStoreLink: String = "", faq: URL? = nil, platformName: String = "", agreement: AgreementConfig, firebase: FirebaseConfig, facebook: FacebookConfig, microsoft: MicrosoftConfig, google: GoogleConfig, appleSignIn: AppleSignInConfig, features: FeaturesConfig, theme: ThemeConfig, uiComponents: UIComponentsConfig, discovery: DiscoveryConfig, dashboard: DashboardConfig, braze: BrazeConfig, branch: BranchConfig, program: DiscoveryConfig, experimentalFeatures: ExperimentalFeaturesConfig, URIScheme: String = "") { + self.baseURL = baseURL + self.baseSSOURL = baseSSOURL + self.ssoFinishedURL = ssoFinishedURL + self.ssoButtonTitle = ssoButtonTitle + self.oAuthClientId = oAuthClientId + self._tokenType = tokenType + self.feedbackEmail = feedbackEmail + self.appStoreLink = appStoreLink + self.faq = faq + self.platformName = platformName + self._agreement = agreement + self._firebase = firebase + self._facebook = facebook + self._microsoft = microsoft + self._google = google + self._appleSignIn = appleSignIn + self._features = features + self._theme = theme + self._uiComponents = uiComponents + self._discovery = discovery + self._dashboard = dashboard + self._braze = braze + self._branch = branch + self._program = program + self._experimentalFeatures = experimentalFeatures + self.URIScheme = URIScheme + } + + + + public var baseURL: URL = URL(fileURLWithPath: "") + + + public var baseSSOURL: URL = URL(fileURLWithPath: "") + + + public var ssoFinishedURL: URL = URL(fileURLWithPath: "") + + + public var ssoButtonTitle: [String: Any] = [String: Any]() + + + public var oAuthClientId: String = "" + + + private var _tokenType: TokenType! + public var tokenType: TokenType { + get { return _tokenType } + set { _tokenType = newValue } + } + + + public var feedbackEmail: String = "" + + + public var appStoreLink: String = "" + + + public var faq: URL? = nil + + + public var platformName: String = "" + + + private var _agreement: AgreementConfig! + public var agreement: AgreementConfig { + get { return _agreement } + set { _agreement = newValue } + } + + + private var _firebase: FirebaseConfig! + public var firebase: FirebaseConfig { + get { return _firebase } + set { _firebase = newValue } + } + + + private var _facebook: FacebookConfig! + public var facebook: FacebookConfig { + get { return _facebook } + set { _facebook = newValue } + } + + + private var _microsoft: MicrosoftConfig! + public var microsoft: MicrosoftConfig { + get { return _microsoft } + set { _microsoft = newValue } + } + + + private var _google: GoogleConfig! + public var google: GoogleConfig { + get { return _google } + set { _google = newValue } + } + + + private var _appleSignIn: AppleSignInConfig! + public var appleSignIn: AppleSignInConfig { + get { return _appleSignIn } + set { _appleSignIn = newValue } + } + + + private var _features: FeaturesConfig! + public var features: FeaturesConfig { + get { return _features } + set { _features = newValue } + } + + + private var _theme: ThemeConfig! + public var theme: ThemeConfig { + get { return _theme } + set { _theme = newValue } + } + + + private var _uiComponents: UIComponentsConfig! + public var uiComponents: UIComponentsConfig { + get { return _uiComponents } + set { _uiComponents = newValue } + } + + + private var _discovery: DiscoveryConfig! + public var discovery: DiscoveryConfig { + get { return _discovery } + set { _discovery = newValue } + } + + + private var _dashboard: DashboardConfig! + public var dashboard: DashboardConfig { + get { return _dashboard } + set { _dashboard = newValue } + } + + + private var _braze: BrazeConfig! + public var braze: BrazeConfig { + get { return _braze } + set { _braze = newValue } + } + + + private var _branch: BranchConfig! + public var branch: BranchConfig { + get { return _branch } + set { _branch = newValue } + } + + + private var _program: DiscoveryConfig! + public var program: DiscoveryConfig { + get { return _program } + set { _program = newValue } + } + + + private var _experimentalFeatures: ExperimentalFeaturesConfig! + public var experimentalFeatures: ExperimentalFeaturesConfig { + get { return _experimentalFeatures } + set { _experimentalFeatures = newValue } + } + + + public var URIScheme: String = "" +} + +public final class CoreAnalyticsMock: CoreAnalytics { + public init() { } + + + public private(set) var trackEventCallCount = 0 + public var trackEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackEventCallCount += 1 + if let trackEventHandler = trackEventHandler { + trackEventHandler(event, parameters) + } + + } + + public private(set) var trackEventBiValueCallCount = 0 + public var trackEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackEventBiValueCallCount += 1 + if let trackEventBiValueHandler = trackEventBiValueHandler { + trackEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var trackScreenEventCallCount = 0 + public var trackScreenEventHandler: ((AnalyticsEvent, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { + trackScreenEventCallCount += 1 + if let trackScreenEventHandler = trackScreenEventHandler { + trackScreenEventHandler(event, parameters) + } + + } + + public private(set) var trackScreenEventBiValueCallCount = 0 + public var trackScreenEventBiValueHandler: ((AnalyticsEvent, EventBIValue, [String: Any]?) -> ())? + public func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { + trackScreenEventBiValueCallCount += 1 + if let trackScreenEventBiValueHandler = trackScreenEventBiValueHandler { + trackScreenEventBiValueHandler(event, biValue, parameters) + } + + } + + public private(set) var appreviewCallCount = 0 + public var appreviewHandler: ((AnalyticsEvent, EventBIValue, String?, Int?) -> ())? + public func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { + appreviewCallCount += 1 + if let appreviewHandler = appreviewHandler { + appreviewHandler(event, biValue, action, rating) + } + + } + + public private(set) var videoQualityChangedCallCount = 0 + public var videoQualityChangedHandler: ((AnalyticsEvent, EventBIValue, String, String) -> ())? + public func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { + videoQualityChangedCallCount += 1 + if let videoQualityChangedHandler = videoQualityChangedHandler { + videoQualityChangedHandler(event, bivalue, value, oldValue) + } + + } +} + +public final class CoreStorageMock: CoreStorage, @unchecked Sendable { + public init() { } + public init(accessToken: String? = nil, refreshToken: String? = nil, pushToken: String? = nil, appleSignFullName: String? = nil, appleSignEmail: String? = nil, cookiesDate: Date? = nil, reviewLastShownVersion: String? = nil, lastReviewDate: Date? = nil, user: DataLayer.User? = nil, userSettings: UserSettings? = nil, resetAppSupportDirectoryUserData: Bool? = nil, useRelativeDates: Bool = false, lastUsedSocialAuth: String? = nil, latestAvailableAppVersion: String? = nil, updateAppRequired: Bool = false) { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.pushToken = pushToken + self.appleSignFullName = appleSignFullName + self.appleSignEmail = appleSignEmail + self.cookiesDate = cookiesDate + self.reviewLastShownVersion = reviewLastShownVersion + self.lastReviewDate = lastReviewDate + self.user = user + self.userSettings = userSettings + self.resetAppSupportDirectoryUserData = resetAppSupportDirectoryUserData + self.useRelativeDates = useRelativeDates + self.lastUsedSocialAuth = lastUsedSocialAuth + self.latestAvailableAppVersion = latestAvailableAppVersion + self.updateAppRequired = updateAppRequired + } + + + public private(set) var accessTokenSetCallCount = 0 + public var accessToken: String? = nil { didSet { accessTokenSetCallCount += 1 } } + + public private(set) var refreshTokenSetCallCount = 0 + public var refreshToken: String? = nil { didSet { refreshTokenSetCallCount += 1 } } + + public private(set) var pushTokenSetCallCount = 0 + public var pushToken: String? = nil { didSet { pushTokenSetCallCount += 1 } } + + public private(set) var appleSignFullNameSetCallCount = 0 + public var appleSignFullName: String? = nil { didSet { appleSignFullNameSetCallCount += 1 } } + + public private(set) var appleSignEmailSetCallCount = 0 + public var appleSignEmail: String? = nil { didSet { appleSignEmailSetCallCount += 1 } } + + public private(set) var cookiesDateSetCallCount = 0 + public var cookiesDate: Date? = nil { didSet { cookiesDateSetCallCount += 1 } } + + public private(set) var reviewLastShownVersionSetCallCount = 0 + public var reviewLastShownVersion: String? = nil { didSet { reviewLastShownVersionSetCallCount += 1 } } + + public private(set) var lastReviewDateSetCallCount = 0 + public var lastReviewDate: Date? = nil { didSet { lastReviewDateSetCallCount += 1 } } + + public private(set) var userSetCallCount = 0 + public var user: DataLayer.User? = nil { didSet { userSetCallCount += 1 } } + + public private(set) var userSettingsSetCallCount = 0 + public var userSettings: UserSettings? = nil { didSet { userSettingsSetCallCount += 1 } } + + public private(set) var resetAppSupportDirectoryUserDataSetCallCount = 0 + public var resetAppSupportDirectoryUserData: Bool? = nil { didSet { resetAppSupportDirectoryUserDataSetCallCount += 1 } } + + public private(set) var useRelativeDatesSetCallCount = 0 + public var useRelativeDates: Bool = false { didSet { useRelativeDatesSetCallCount += 1 } } + + public private(set) var lastUsedSocialAuthSetCallCount = 0 + public var lastUsedSocialAuth: String? = nil { didSet { lastUsedSocialAuthSetCallCount += 1 } } + + public private(set) var latestAvailableAppVersionSetCallCount = 0 + public var latestAvailableAppVersion: String? = nil { didSet { latestAvailableAppVersionSetCallCount += 1 } } + + public private(set) var updateAppRequiredSetCallCount = 0 + public var updateAppRequired: Bool = false { didSet { updateAppRequiredSetCallCount += 1 } } + + private let clearState = MockoloMutex(MockoloHandlerState ()>()) + public var clearCallCount: Int { + return clearState.withLock(\.callCount) + } + public var clearHandler: (@Sendable () -> ())? { + get { clearState.withLock(\.handler) } + set { clearState.withLock { $0.handler = newValue } } + } + public func clear() { + let clearHandler = clearState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearHandler = clearHandler { + clearHandler() + } + + } +} + +public final class AuthInteractorProtocolMock: AuthInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let loginState = MockoloMutex(MockoloHandlerState User>()) + public var loginCallCount: Int { + return loginState.withLock(\.callCount) + } + public var loginHandler: (@Sendable (String, String) async throws -> User)? { + get { loginState.withLock(\.handler) } + set { loginState.withLock { $0.handler = newValue } } + } + public func login(username: String, password: String) async throws -> User { + let loginHandler = loginState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginHandler = loginHandler { + return try await loginHandler(username, password) + } + fatalError("loginHandler returns can't have a default value thus its handler must be set") + } + + private let loginExternalTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginExternalTokenCallCount: Int { + return loginExternalTokenState.withLock(\.callCount) + } + public var loginExternalTokenHandler: (@Sendable (String, String) async throws -> User)? { + get { loginExternalTokenState.withLock(\.handler) } + set { loginExternalTokenState.withLock { $0.handler = newValue } } + } + public func login(externalToken: String, backend: String) async throws -> User { + let loginExternalTokenHandler = loginExternalTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginExternalTokenHandler = loginExternalTokenHandler { + return try await loginExternalTokenHandler(externalToken, backend) + } + fatalError("loginExternalTokenHandler returns can't have a default value thus its handler must be set") + } + + private let loginSsoTokenState = MockoloMutex(MockoloHandlerState User>()) + public var loginSsoTokenCallCount: Int { + return loginSsoTokenState.withLock(\.callCount) + } + public var loginSsoTokenHandler: (@Sendable (String) async throws -> User)? { + get { loginSsoTokenState.withLock(\.handler) } + set { loginSsoTokenState.withLock { $0.handler = newValue } } + } + public func login(ssoToken: String) async throws -> User { + let loginSsoTokenHandler = loginSsoTokenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loginSsoTokenHandler = loginSsoTokenHandler { + return try await loginSsoTokenHandler(ssoToken) + } + fatalError("loginSsoTokenHandler returns can't have a default value thus its handler must be set") + } + + private let resetPasswordState = MockoloMutex(MockoloHandlerState ResetPassword>()) + public var resetPasswordCallCount: Int { + return resetPasswordState.withLock(\.callCount) + } + public var resetPasswordHandler: (@Sendable (String) async throws -> ResetPassword)? { + get { resetPasswordState.withLock(\.handler) } + set { resetPasswordState.withLock { $0.handler = newValue } } + } + public func resetPassword(email: String) async throws -> ResetPassword { + let resetPasswordHandler = resetPasswordState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resetPasswordHandler = resetPasswordHandler { + return try await resetPasswordHandler(email) + } + fatalError("resetPasswordHandler returns can't have a default value thus its handler must be set") + } + + private let getCookiesState = MockoloMutex(MockoloHandlerState ()>()) + public var getCookiesCallCount: Int { + return getCookiesState.withLock(\.callCount) + } + public var getCookiesHandler: (@Sendable (Bool) async throws -> ())? { + get { getCookiesState.withLock(\.handler) } + set { getCookiesState.withLock { $0.handler = newValue } } + } + public func getCookies(force: Bool) async throws { + let getCookiesHandler = getCookiesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCookiesHandler = getCookiesHandler { + try await getCookiesHandler(force) + } + + } + + private let getRegistrationFieldsState = MockoloMutex(MockoloHandlerState [PickerFields]>()) + public var getRegistrationFieldsCallCount: Int { + return getRegistrationFieldsState.withLock(\.callCount) + } + public var getRegistrationFieldsHandler: (@Sendable () async throws -> [PickerFields])? { + get { getRegistrationFieldsState.withLock(\.handler) } + set { getRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func getRegistrationFields() async throws -> [PickerFields] { + let getRegistrationFieldsHandler = getRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getRegistrationFieldsHandler = getRegistrationFieldsHandler { + return try await getRegistrationFieldsHandler() + } + return [PickerFields]() + } + + private let registerUserState = MockoloMutex(MockoloHandlerState User>()) + public var registerUserCallCount: Int { + return registerUserState.withLock(\.callCount) + } + public var registerUserHandler: (@Sendable ([String: String], Bool) async throws -> User)? { + get { registerUserState.withLock(\.handler) } + set { registerUserState.withLock { $0.handler = newValue } } + } + public func registerUser(fields: [String: String], isSocial: Bool) async throws -> User { + let registerUserHandler = registerUserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let registerUserHandler = registerUserHandler { + return try await registerUserHandler(fields, isSocial) + } + fatalError("registerUserHandler returns can't have a default value thus its handler must be set") + } + + private let validateRegistrationFieldsState = MockoloMutex(MockoloHandlerState [String: String]>()) + public var validateRegistrationFieldsCallCount: Int { + return validateRegistrationFieldsState.withLock(\.callCount) + } + public var validateRegistrationFieldsHandler: (@Sendable ([String: String]) async throws -> [String: String])? { + get { validateRegistrationFieldsState.withLock(\.handler) } + set { validateRegistrationFieldsState.withLock { $0.handler = newValue } } + } + public func validateRegistrationFields(fields: [String: String]) async throws -> [String: String] { + let validateRegistrationFieldsHandler = validateRegistrationFieldsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let validateRegistrationFieldsHandler = validateRegistrationFieldsHandler { + return try await validateRegistrationFieldsHandler(fields) + } + return [String: String]() + } +} + +public final class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let submitOfflineProgressState = MockoloMutex(MockoloHandlerState Bool>()) + public var submitOfflineProgressCallCount: Int { + return submitOfflineProgressState.withLock(\.callCount) + } + public var submitOfflineProgressHandler: (@Sendable (String, String, String) async throws -> Bool)? { + get { submitOfflineProgressState.withLock(\.handler) } + set { submitOfflineProgressState.withLock { $0.handler = newValue } } + } + public func submitOfflineProgress(courseID: String, blockID: String, data: String) async throws -> Bool { + let submitOfflineProgressHandler = submitOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let submitOfflineProgressHandler = submitOfflineProgressHandler { + return try await submitOfflineProgressHandler(courseID, blockID, data) + } + return false + } +} + +public final class WebviewCookiesUpdateProtocolMock: WebviewCookiesUpdateProtocol { + public init() { } + public init(authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock(), cookiesReady: Bool = false, updatingCookies: Bool = false, errorMessage: String? = nil) { + self.authInteractor = authInteractor + self.cookiesReady = cookiesReady + self.updatingCookies = updatingCookies + self.errorMessage = errorMessage + } + + + + public var authInteractor: AuthInteractorProtocol = AuthInteractorProtocolMock() + + public private(set) var cookiesReadySetCallCount = 0 + public var cookiesReady: Bool = false { didSet { cookiesReadySetCallCount += 1 } } + + public private(set) var updatingCookiesSetCallCount = 0 + public var updatingCookies: Bool = false { didSet { updatingCookiesSetCallCount += 1 } } + + public private(set) var errorMessageSetCallCount = 0 + public var errorMessage: String? = nil { didSet { errorMessageSetCallCount += 1 } } + + public private(set) var updateCookiesCallCount = 0 + public var updateCookiesHandler: ((Bool, Int) async -> ())? + public func updateCookies(force: Bool, retryCount: Int) async { + updateCookiesCallCount += 1 + if let updateCookiesHandler = updateCookiesHandler { + await updateCookiesHandler(force, retryCount) + } + + } +} + +public final class BaseRouterMock: BaseRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class CalendarManagerProtocolMock: CalendarManagerProtocol, @unchecked Sendable { + public init() { } + + + private let createCalendarIfNeededState = MockoloMutex(MockoloHandlerState ()>()) + public var createCalendarIfNeededCallCount: Int { + return createCalendarIfNeededState.withLock(\.callCount) + } + public var createCalendarIfNeededHandler: (@Sendable () -> ())? { + get { createCalendarIfNeededState.withLock(\.handler) } + set { createCalendarIfNeededState.withLock { $0.handler = newValue } } + } + public func createCalendarIfNeeded() { + let createCalendarIfNeededHandler = createCalendarIfNeededState.withLock { state in + state.callCount += 1 + return state.handler + } + if let createCalendarIfNeededHandler = createCalendarIfNeededHandler { + createCalendarIfNeededHandler() + } + + } + + private let filterCoursesBySelectedState = MockoloMutex(MockoloHandlerState [CourseForSync]>()) + public var filterCoursesBySelectedCallCount: Int { + return filterCoursesBySelectedState.withLock(\.callCount) + } + public var filterCoursesBySelectedHandler: (@Sendable ([CourseForSync]) async -> [CourseForSync])? { + get { filterCoursesBySelectedState.withLock(\.handler) } + set { filterCoursesBySelectedState.withLock { $0.handler = newValue } } + } + public func filterCoursesBySelected(fetchedCourses: [CourseForSync]) async -> [CourseForSync] { + let filterCoursesBySelectedHandler = filterCoursesBySelectedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let filterCoursesBySelectedHandler = filterCoursesBySelectedHandler { + return await filterCoursesBySelectedHandler(fetchedCourses) + } + return [CourseForSync]() + } + + private let removeOldCalendarState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOldCalendarCallCount: Int { + return removeOldCalendarState.withLock(\.callCount) + } + public var removeOldCalendarHandler: (@Sendable () -> ())? { + get { removeOldCalendarState.withLock(\.handler) } + set { removeOldCalendarState.withLock { $0.handler = newValue } } + } + public func removeOldCalendar() { + let removeOldCalendarHandler = removeOldCalendarState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOldCalendarHandler = removeOldCalendarHandler { + removeOldCalendarHandler() + } + + } + + private let removeOutdatedEventsState = MockoloMutex(MockoloHandlerState ()>()) + public var removeOutdatedEventsCallCount: Int { + return removeOutdatedEventsState.withLock(\.callCount) + } + public var removeOutdatedEventsHandler: (@Sendable (String) async -> ())? { + get { removeOutdatedEventsState.withLock(\.handler) } + set { removeOutdatedEventsState.withLock { $0.handler = newValue } } + } + public func removeOutdatedEvents(courseID: String) async { + let removeOutdatedEventsHandler = removeOutdatedEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeOutdatedEventsHandler = removeOutdatedEventsHandler { + await removeOutdatedEventsHandler(courseID) + } + + } + + private let syncCourseState = MockoloMutex(MockoloHandlerState ()>()) + public var syncCourseCallCount: Int { + return syncCourseState.withLock(\.callCount) + } + public var syncCourseHandler: (@Sendable (String, String, CourseDates) async -> ())? { + get { syncCourseState.withLock(\.handler) } + set { syncCourseState.withLock { $0.handler = newValue } } + } + public func syncCourse(courseID: String, courseName: String, dates: CourseDates) async { + let syncCourseHandler = syncCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let syncCourseHandler = syncCourseHandler { + await syncCourseHandler(courseID, courseName, dates) + } + + } + + private let requestAccessState = MockoloMutex(MockoloHandlerState Bool>()) + public var requestAccessCallCount: Int { + return requestAccessState.withLock(\.callCount) + } + public var requestAccessHandler: (@Sendable () async -> Bool)? { + get { requestAccessState.withLock(\.handler) } + set { requestAccessState.withLock { $0.handler = newValue } } + } + public func requestAccess() async -> Bool { + let requestAccessHandler = requestAccessState.withLock { state in + state.callCount += 1 + return state.handler + } + if let requestAccessHandler = requestAccessHandler { + return await requestAccessHandler() + } + return false + } + + private let courseStatusState = MockoloMutex(MockoloHandlerState SyncStatus>()) + public var courseStatusCallCount: Int { + return courseStatusState.withLock(\.callCount) + } + public var courseStatusHandler: (@Sendable (String) async -> SyncStatus)? { + get { courseStatusState.withLock(\.handler) } + set { courseStatusState.withLock { $0.handler = newValue } } + } + public func courseStatus(courseID: String) async -> SyncStatus { + let courseStatusHandler = courseStatusState.withLock { state in + state.callCount += 1 + return state.handler + } + if let courseStatusHandler = courseStatusHandler { + return await courseStatusHandler(courseID) + } + fatalError("courseStatusHandler returns can't have a default value thus its handler must be set") + } + + private let clearAllDataState = MockoloMutex(MockoloHandlerState ()>()) + public var clearAllDataCallCount: Int { + return clearAllDataState.withLock(\.callCount) + } + public var clearAllDataHandler: (@Sendable (Bool) async -> ())? { + get { clearAllDataState.withLock(\.handler) } + set { clearAllDataState.withLock { $0.handler = newValue } } + } + public func clearAllData(removeCalendar: Bool) async { + let clearAllDataHandler = clearAllDataState.withLock { state in + state.callCount += 1 + return state.handler + } + if let clearAllDataHandler = clearAllDataHandler { + await clearAllDataHandler(removeCalendar) + } + + } + + private let isDatesChangedState = MockoloMutex(MockoloHandlerState Bool>()) + public var isDatesChangedCallCount: Int { + return isDatesChangedState.withLock(\.callCount) + } + public var isDatesChangedHandler: (@Sendable (String, String) async -> Bool)? { + get { isDatesChangedState.withLock(\.handler) } + set { isDatesChangedState.withLock { $0.handler = newValue } } + } + public func isDatesChanged(courseID: String, checksum: String) async -> Bool { + let isDatesChangedHandler = isDatesChangedState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isDatesChangedHandler = isDatesChangedHandler { + return await isDatesChangedHandler(courseID, checksum) + } + return false + } +} + +public final class CorePersistenceProtocolMock: CorePersistenceProtocol, @unchecked Sendable { + public init() { } + + + private let setState = MockoloMutex(MockoloHandlerState ()>()) + public var setCallCount: Int { + return setState.withLock(\.callCount) + } + public var setHandler: (@Sendable (Int) -> ())? { + get { setState.withLock(\.handler) } + set { setState.withLock { $0.handler = newValue } } + } + public func set(userId: Int) { + let setHandler = setState.withLock { state in + state.callCount += 1 + return state.handler + } + if let setHandler = setHandler { + setHandler(userId) + } + + } + + private let getUserIDState = MockoloMutex(MockoloHandlerState Int?>()) + public var getUserIDCallCount: Int { + return getUserIDState.withLock(\.callCount) + } + public var getUserIDHandler: (@Sendable () -> Int?)? { + get { getUserIDState.withLock(\.handler) } + set { getUserIDState.withLock { $0.handler = newValue } } + } + public func getUserID() -> Int? { + let getUserIDHandler = getUserIDState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getUserIDHandler = getUserIDHandler { + return getUserIDHandler() + } + return nil + } + + private let publisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var publisherCallCount: Int { + return publisherState.withLock(\.callCount) + } + public var publisherHandler: (@Sendable () throws -> AnyPublisher)? { + get { publisherState.withLock(\.handler) } + set { publisherState.withLock { $0.handler = newValue } } + } + public func publisher() throws -> AnyPublisher { + let publisherHandler = publisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let publisherHandler = publisherHandler { + return try publisherHandler() + } + fatalError("publisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([DownloadDataTask]) -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(tasks: [DownloadDataTask]) { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + addToDownloadQueueHandler(tasks) + } + + } + + private let saveOfflineProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var saveOfflineProgressCallCount: Int { + return saveOfflineProgressState.withLock(\.callCount) + } + public var saveOfflineProgressHandler: (@Sendable (OfflineProgress) async -> ())? { + get { saveOfflineProgressState.withLock(\.handler) } + set { saveOfflineProgressState.withLock { $0.handler = newValue } } + } + public func saveOfflineProgress(progress: OfflineProgress) async { + let saveOfflineProgressHandler = saveOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveOfflineProgressHandler = saveOfflineProgressHandler { + await saveOfflineProgressHandler(progress) + } + + } + + private let loadProgressState = MockoloMutex(MockoloHandlerState OfflineProgress?>()) + public var loadProgressCallCount: Int { + return loadProgressState.withLock(\.callCount) + } + public var loadProgressHandler: (@Sendable (String) async -> OfflineProgress?)? { + get { loadProgressState.withLock(\.handler) } + set { loadProgressState.withLock { $0.handler = newValue } } + } + public func loadProgress(for blockID: String) async -> OfflineProgress? { + let loadProgressHandler = loadProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadProgressHandler = loadProgressHandler { + return await loadProgressHandler(blockID) + } + return nil + } + + private let loadAllOfflineProgressState = MockoloMutex(MockoloHandlerState [OfflineProgress]>()) + public var loadAllOfflineProgressCallCount: Int { + return loadAllOfflineProgressState.withLock(\.callCount) + } + public var loadAllOfflineProgressHandler: (@Sendable () async -> [OfflineProgress])? { + get { loadAllOfflineProgressState.withLock(\.handler) } + set { loadAllOfflineProgressState.withLock { $0.handler = newValue } } + } + public func loadAllOfflineProgress() async -> [OfflineProgress] { + let loadAllOfflineProgressHandler = loadAllOfflineProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let loadAllOfflineProgressHandler = loadAllOfflineProgressHandler { + return await loadAllOfflineProgressHandler() + } + return [OfflineProgress]() + } + + private let deleteProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteProgressCallCount: Int { + return deleteProgressState.withLock(\.callCount) + } + public var deleteProgressHandler: (@Sendable (String) async -> ())? { + get { deleteProgressState.withLock(\.handler) } + set { deleteProgressState.withLock { $0.handler = newValue } } + } + public func deleteProgress(for blockID: String) async { + let deleteProgressHandler = deleteProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteProgressHandler = deleteProgressHandler { + await deleteProgressHandler(blockID) + } + + } + + private let deleteAllProgressState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllProgressCallCount: Int { + return deleteAllProgressState.withLock(\.callCount) + } + public var deleteAllProgressHandler: (@Sendable () async -> ())? { + get { deleteAllProgressState.withLock(\.handler) } + set { deleteAllProgressState.withLock { $0.handler = newValue } } + } + public func deleteAllProgress() async { + let deleteAllProgressHandler = deleteAllProgressState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllProgressHandler = deleteAllProgressHandler { + await deleteAllProgressHandler() + } + + } + + private let addToDownloadQueueBlocksState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueBlocksCallCount: Int { + return addToDownloadQueueBlocksState.withLock(\.callCount) + } + public var addToDownloadQueueBlocksHandler: (@Sendable ([CourseBlock], DownloadQuality) -> ())? { + get { addToDownloadQueueBlocksState.withLock(\.handler) } + set { addToDownloadQueueBlocksState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { + let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueBlocksHandler = addToDownloadQueueBlocksHandler { + addToDownloadQueueBlocksHandler(blocks, downloadQuality) + } + + } + + private let updateTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var updateTaskCallCount: Int { + return updateTaskState.withLock(\.callCount) + } + public var updateTaskHandler: (@Sendable (DownloadDataTask) -> ())? { + get { updateTaskState.withLock(\.handler) } + set { updateTaskState.withLock { $0.handler = newValue } } + } + public func updateTask(task: DownloadDataTask) { + let updateTaskHandler = updateTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateTaskHandler = updateTaskHandler { + updateTaskHandler(task) + } + + } + + private let downloadDataTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadDataTaskCallCount: Int { + return downloadDataTaskState.withLock(\.callCount) + } + public var downloadDataTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadDataTaskState.withLock(\.handler) } + set { downloadDataTaskState.withLock { $0.handler = newValue } } + } + public func downloadDataTask(for blockId: String) async -> DownloadDataTask? { + let downloadDataTaskHandler = downloadDataTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadDataTaskHandler = downloadDataTaskHandler { + return await downloadDataTaskHandler(blockId) + } + return nil + } + + private let getDownloadDataTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksCallCount: Int { + return getDownloadDataTasksState.withLock(\.callCount) + } + public var getDownloadDataTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadDataTasksState.withLock(\.handler) } + set { getDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasks() async -> [DownloadDataTask] { + let getDownloadDataTasksHandler = getDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksHandler = getDownloadDataTasksHandler { + return await getDownloadDataTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadDataTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadDataTasksForCourseCallCount: Int { + return getDownloadDataTasksForCourseState.withLock(\.callCount) + } + public var getDownloadDataTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadDataTasksForCourseState.withLock(\.handler) } + set { getDownloadDataTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadDataTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadDataTasksForCourseHandler = getDownloadDataTasksForCourseHandler { + return await getDownloadDataTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let deleteDownloadDataTasksState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteDownloadDataTasksCallCount: Int { + return deleteDownloadDataTasksState.withLock(\.callCount) + } + public var deleteDownloadDataTasksHandler: (@Sendable ([String]) -> ())? { + get { deleteDownloadDataTasksState.withLock(\.handler) } + set { deleteDownloadDataTasksState.withLock { $0.handler = newValue } } + } + public func deleteDownloadDataTasks(ids: [String]) { + let deleteDownloadDataTasksHandler = deleteDownloadDataTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteDownloadDataTasksHandler = deleteDownloadDataTasksHandler { + deleteDownloadDataTasksHandler(ids) + } + + } +} + +public final class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getCourseBlocksCallCount: Int { + return getCourseBlocksState.withLock(\.callCount) + } + public var getCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getCourseBlocksState.withLock(\.handler) } + set { getCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getCourseBlocks(courseID: String) async throws -> CourseStructure { + let getCourseBlocksHandler = getCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseBlocksHandler = getCourseBlocksHandler { + return try await getCourseBlocksHandler(courseID) + } + fatalError("getCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let getLoadedCourseBlocksState = MockoloMutex(MockoloHandlerState CourseStructure>()) + public var getLoadedCourseBlocksCallCount: Int { + return getLoadedCourseBlocksState.withLock(\.callCount) + } + public var getLoadedCourseBlocksHandler: (@Sendable (String) async throws -> CourseStructure)? { + get { getLoadedCourseBlocksState.withLock(\.handler) } + set { getLoadedCourseBlocksState.withLock { $0.handler = newValue } } + } + public func getLoadedCourseBlocks(courseID: String) async throws -> CourseStructure { + let getLoadedCourseBlocksHandler = getLoadedCourseBlocksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getLoadedCourseBlocksHandler = getLoadedCourseBlocksHandler { + return try await getLoadedCourseBlocksHandler(courseID) + } + fatalError("getLoadedCourseBlocksHandler returns can't have a default value thus its handler must be set") + } + + private let shiftDueDatesState = MockoloMutex(MockoloHandlerState ()>()) + public var shiftDueDatesCallCount: Int { + return shiftDueDatesState.withLock(\.callCount) + } + public var shiftDueDatesHandler: (@Sendable (String) async throws -> ())? { + get { shiftDueDatesState.withLock(\.handler) } + set { shiftDueDatesState.withLock { $0.handler = newValue } } + } + public func shiftDueDates(courseID: String) async throws { + let shiftDueDatesHandler = shiftDueDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let shiftDueDatesHandler = shiftDueDatesHandler { + try await shiftDueDatesHandler(courseID) + } + + } +} + +public final class ProfilePersistenceProtocolMock: ProfilePersistenceProtocol, @unchecked Sendable { + public init() { } + + + private let getCourseStateState = MockoloMutex(MockoloHandlerState CourseCalendarState?>()) + public var getCourseStateCallCount: Int { + return getCourseStateState.withLock(\.callCount) + } + public var getCourseStateHandler: (@Sendable (String) async -> CourseCalendarState?)? { + get { getCourseStateState.withLock(\.handler) } + set { getCourseStateState.withLock { $0.handler = newValue } } + } + public func getCourseState(courseID: String) async -> CourseCalendarState? { + let getCourseStateHandler = getCourseStateState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseStateHandler = getCourseStateHandler { + return await getCourseStateHandler(courseID) + } + return nil + } + + private let getAllCourseStatesState = MockoloMutex(MockoloHandlerState [CourseCalendarState]>()) + public var getAllCourseStatesCallCount: Int { + return getAllCourseStatesState.withLock(\.callCount) + } + public var getAllCourseStatesHandler: (@Sendable () async -> [CourseCalendarState])? { + get { getAllCourseStatesState.withLock(\.handler) } + set { getAllCourseStatesState.withLock { $0.handler = newValue } } + } + public func getAllCourseStates() async -> [CourseCalendarState] { + let getAllCourseStatesHandler = getAllCourseStatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getAllCourseStatesHandler = getAllCourseStatesHandler { + return await getAllCourseStatesHandler() + } + return [CourseCalendarState]() + } + + private let saveCourseStateState = MockoloMutex(MockoloHandlerState ()>()) + public var saveCourseStateCallCount: Int { + return saveCourseStateState.withLock(\.callCount) + } + public var saveCourseStateHandler: (@Sendable (CourseCalendarState) async -> ())? { + get { saveCourseStateState.withLock(\.handler) } + set { saveCourseStateState.withLock { $0.handler = newValue } } + } + public func saveCourseState(state: CourseCalendarState) async { + let saveCourseStateHandler = saveCourseStateState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveCourseStateHandler = saveCourseStateHandler { + await saveCourseStateHandler(state) + } + + } + + private let removeCourseStateState = MockoloMutex(MockoloHandlerState ()>()) + public var removeCourseStateCallCount: Int { + return removeCourseStateState.withLock(\.callCount) + } + public var removeCourseStateHandler: (@Sendable (String) async -> ())? { + get { removeCourseStateState.withLock(\.handler) } + set { removeCourseStateState.withLock { $0.handler = newValue } } + } + public func removeCourseState(courseID: String) async { + let removeCourseStateHandler = removeCourseStateState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeCourseStateHandler = removeCourseStateHandler { + await removeCourseStateHandler(courseID) + } + + } + + private let deleteAllCourseStatesAndEventsState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllCourseStatesAndEventsCallCount: Int { + return deleteAllCourseStatesAndEventsState.withLock(\.callCount) + } + public var deleteAllCourseStatesAndEventsHandler: (@Sendable () async -> ())? { + get { deleteAllCourseStatesAndEventsState.withLock(\.handler) } + set { deleteAllCourseStatesAndEventsState.withLock { $0.handler = newValue } } + } + public func deleteAllCourseStatesAndEvents() async { + let deleteAllCourseStatesAndEventsHandler = deleteAllCourseStatesAndEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllCourseStatesAndEventsHandler = deleteAllCourseStatesAndEventsHandler { + await deleteAllCourseStatesAndEventsHandler() + } + + } + + private let saveCourseCalendarEventState = MockoloMutex(MockoloHandlerState ()>()) + public var saveCourseCalendarEventCallCount: Int { + return saveCourseCalendarEventState.withLock(\.callCount) + } + public var saveCourseCalendarEventHandler: (@Sendable (CourseCalendarEvent) async -> ())? { + get { saveCourseCalendarEventState.withLock(\.handler) } + set { saveCourseCalendarEventState.withLock { $0.handler = newValue } } + } + public func saveCourseCalendarEvent(_ event: CourseCalendarEvent) async { + let saveCourseCalendarEventHandler = saveCourseCalendarEventState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveCourseCalendarEventHandler = saveCourseCalendarEventHandler { + await saveCourseCalendarEventHandler(event) + } + + } + + private let removeCourseCalendarEventsState = MockoloMutex(MockoloHandlerState ()>()) + public var removeCourseCalendarEventsCallCount: Int { + return removeCourseCalendarEventsState.withLock(\.callCount) + } + public var removeCourseCalendarEventsHandler: (@Sendable (String) async -> ())? { + get { removeCourseCalendarEventsState.withLock(\.handler) } + set { removeCourseCalendarEventsState.withLock { $0.handler = newValue } } + } + public func removeCourseCalendarEvents(for courseId: String) async { + let removeCourseCalendarEventsHandler = removeCourseCalendarEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeCourseCalendarEventsHandler = removeCourseCalendarEventsHandler { + await removeCourseCalendarEventsHandler(courseId) + } + + } + + private let removeAllCourseCalendarEventsState = MockoloMutex(MockoloHandlerState ()>()) + public var removeAllCourseCalendarEventsCallCount: Int { + return removeAllCourseCalendarEventsState.withLock(\.callCount) + } + public var removeAllCourseCalendarEventsHandler: (@Sendable () async -> ())? { + get { removeAllCourseCalendarEventsState.withLock(\.handler) } + set { removeAllCourseCalendarEventsState.withLock { $0.handler = newValue } } + } + public func removeAllCourseCalendarEvents() async { + let removeAllCourseCalendarEventsHandler = removeAllCourseCalendarEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeAllCourseCalendarEventsHandler = removeAllCourseCalendarEventsHandler { + await removeAllCourseCalendarEventsHandler() + } + + } + + private let getCourseCalendarEventsState = MockoloMutex(MockoloHandlerState [CourseCalendarEvent]>()) + public var getCourseCalendarEventsCallCount: Int { + return getCourseCalendarEventsState.withLock(\.callCount) + } + public var getCourseCalendarEventsHandler: (@Sendable (String) async -> [CourseCalendarEvent])? { + get { getCourseCalendarEventsState.withLock(\.handler) } + set { getCourseCalendarEventsState.withLock { $0.handler = newValue } } + } + public func getCourseCalendarEvents(for courseId: String) async -> [CourseCalendarEvent] { + let getCourseCalendarEventsHandler = getCourseCalendarEventsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseCalendarEventsHandler = getCourseCalendarEventsHandler { + return await getCourseCalendarEventsHandler(courseId) + } + return [CourseCalendarEvent]() + } +} + +public final class ProfileRouterMock: ProfileRouter, @unchecked Sendable { + public init() { } + + + private let backToRootState = MockoloMutex(MockoloHandlerState ()>()) + public var backToRootCallCount: Int { + return backToRootState.withLock(\.callCount) + } + public var backToRootHandler: (@Sendable (Bool) -> ())? { + get { backToRootState.withLock(\.handler) } + set { backToRootState.withLock { $0.handler = newValue } } + } + public func backToRoot(animated: Bool) { + let backToRootHandler = backToRootState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backToRootHandler = backToRootHandler { + backToRootHandler(animated) + } + + } + + private let showEditProfileState = MockoloMutex(MockoloHandlerState Void) -> ()>()) + public var showEditProfileCallCount: Int { + return showEditProfileState.withLock(\.callCount) + } + public var showEditProfileHandler: (@Sendable (Core.UserProfile, UIImage?, @escaping ((UserProfile?, UIImage?)) -> Void) -> ())? { + get { showEditProfileState.withLock(\.handler) } + set { showEditProfileState.withLock { $0.handler = newValue } } + } + public func showEditProfile(userModel: Core.UserProfile, avatar: UIImage?, profileDidEdit: @escaping ((UserProfile?, UIImage?)) -> Void) { + let showEditProfileHandler = showEditProfileState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showEditProfileHandler = showEditProfileHandler { + showEditProfileHandler(userModel, avatar, profileDidEdit) + } + + } + + private let backState = MockoloMutex(MockoloHandlerState ()>()) + public var backCallCount: Int { + return backState.withLock(\.callCount) + } + public var backHandler: (@Sendable (Bool) -> ())? { + get { backState.withLock(\.handler) } + set { backState.withLock { $0.handler = newValue } } + } + public func back(animated: Bool) { + let backHandler = backState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backHandler = backHandler { + backHandler(animated) + } + + } + + private let backWithFadeState = MockoloMutex(MockoloHandlerState ()>()) + public var backWithFadeCallCount: Int { + return backWithFadeState.withLock(\.callCount) + } + public var backWithFadeHandler: (@Sendable () -> ())? { + get { backWithFadeState.withLock(\.handler) } + set { backWithFadeState.withLock { $0.handler = newValue } } + } + public func backWithFade() { + let backWithFadeHandler = backWithFadeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let backWithFadeHandler = backWithFadeHandler { + backWithFadeHandler() + } + + } + + private let dismissState = MockoloMutex(MockoloHandlerState ()>()) + public var dismissCallCount: Int { + return dismissState.withLock(\.callCount) + } + public var dismissHandler: (@Sendable (Bool) -> ())? { + get { dismissState.withLock(\.handler) } + set { dismissState.withLock { $0.handler = newValue } } + } + public func dismiss(animated: Bool) { + let dismissHandler = dismissState.withLock { state in + state.callCount += 1 + return state.handler + } + if let dismissHandler = dismissHandler { + dismissHandler(animated) + } + + } + + private let removeLastViewState = MockoloMutex(MockoloHandlerState ()>()) + public var removeLastViewCallCount: Int { + return removeLastViewState.withLock(\.callCount) + } + public var removeLastViewHandler: (@Sendable (Int) -> ())? { + get { removeLastViewState.withLock(\.handler) } + set { removeLastViewState.withLock { $0.handler = newValue } } + } + public func removeLastView(controllers: Int) { + let removeLastViewHandler = removeLastViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeLastViewHandler = removeLastViewHandler { + removeLastViewHandler(controllers) + } + + } + + private let showMainOrWhatsNewScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showMainOrWhatsNewScreenCallCount: Int { + return showMainOrWhatsNewScreenState.withLock(\.callCount) + } + public var showMainOrWhatsNewScreenHandler: (@Sendable (LogistrationSourceScreen, PostLoginData?) -> ())? { + get { showMainOrWhatsNewScreenState.withLock(\.handler) } + set { showMainOrWhatsNewScreenState.withLock { $0.handler = newValue } } + } + public func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { + let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showMainOrWhatsNewScreenHandler = showMainOrWhatsNewScreenHandler { + showMainOrWhatsNewScreenHandler(sourceScreen, postLoginData) + } + + } + + private let showSettingsState = MockoloMutex(MockoloHandlerState ()>()) + public var showSettingsCallCount: Int { + return showSettingsState.withLock(\.callCount) + } + public var showSettingsHandler: (@Sendable () -> ())? { + get { showSettingsState.withLock(\.handler) } + set { showSettingsState.withLock { $0.handler = newValue } } + } + public func showSettings() { + let showSettingsHandler = showSettingsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSettingsHandler = showSettingsHandler { + showSettingsHandler() + } + + } + + private let showVideoSettingsState = MockoloMutex(MockoloHandlerState ()>()) + public var showVideoSettingsCallCount: Int { + return showVideoSettingsState.withLock(\.callCount) + } + public var showVideoSettingsHandler: (@Sendable () -> ())? { + get { showVideoSettingsState.withLock(\.handler) } + set { showVideoSettingsState.withLock { $0.handler = newValue } } + } + public func showVideoSettings() { + let showVideoSettingsHandler = showVideoSettingsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showVideoSettingsHandler = showVideoSettingsHandler { + showVideoSettingsHandler() + } + + } + + private let showManageAccountState = MockoloMutex(MockoloHandlerState ()>()) + public var showManageAccountCallCount: Int { + return showManageAccountState.withLock(\.callCount) + } + public var showManageAccountHandler: (@Sendable () -> ())? { + get { showManageAccountState.withLock(\.handler) } + set { showManageAccountState.withLock { $0.handler = newValue } } + } + public func showManageAccount() { + let showManageAccountHandler = showManageAccountState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showManageAccountHandler = showManageAccountHandler { + showManageAccountHandler() + } + + } + + private let showDatesAndCalendarState = MockoloMutex(MockoloHandlerState ()>()) + public var showDatesAndCalendarCallCount: Int { + return showDatesAndCalendarState.withLock(\.callCount) + } + public var showDatesAndCalendarHandler: (@Sendable () -> ())? { + get { showDatesAndCalendarState.withLock(\.handler) } + set { showDatesAndCalendarState.withLock { $0.handler = newValue } } + } + public func showDatesAndCalendar() { + let showDatesAndCalendarHandler = showDatesAndCalendarState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDatesAndCalendarHandler = showDatesAndCalendarHandler { + showDatesAndCalendarHandler() + } + + } + + private let showStartupScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showStartupScreenCallCount: Int { + return showStartupScreenState.withLock(\.callCount) + } + public var showStartupScreenHandler: (@Sendable () -> ())? { + get { showStartupScreenState.withLock(\.handler) } + set { showStartupScreenState.withLock { $0.handler = newValue } } + } + public func showStartupScreen() { + let showStartupScreenHandler = showStartupScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showStartupScreenHandler = showStartupScreenHandler { + showStartupScreenHandler() + } + + } + + private let showSyncCalendarOptionsState = MockoloMutex(MockoloHandlerState ()>()) + public var showSyncCalendarOptionsCallCount: Int { + return showSyncCalendarOptionsState.withLock(\.callCount) + } + public var showSyncCalendarOptionsHandler: (@Sendable () -> ())? { + get { showSyncCalendarOptionsState.withLock(\.handler) } + set { showSyncCalendarOptionsState.withLock { $0.handler = newValue } } + } + public func showSyncCalendarOptions() { + let showSyncCalendarOptionsHandler = showSyncCalendarOptionsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSyncCalendarOptionsHandler = showSyncCalendarOptionsHandler { + showSyncCalendarOptionsHandler() + } + + } + + private let showLoginScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showLoginScreenCallCount: Int { + return showLoginScreenState.withLock(\.callCount) + } + public var showLoginScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showLoginScreenState.withLock(\.handler) } + set { showLoginScreenState.withLock { $0.handler = newValue } } + } + public func showLoginScreen(sourceScreen: LogistrationSourceScreen) { + let showLoginScreenHandler = showLoginScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showLoginScreenHandler = showLoginScreenHandler { + showLoginScreenHandler(sourceScreen) + } + + } + + private let showCoursesToSyncState = MockoloMutex(MockoloHandlerState ()>()) + public var showCoursesToSyncCallCount: Int { + return showCoursesToSyncState.withLock(\.callCount) + } + public var showCoursesToSyncHandler: (@Sendable () -> ())? { + get { showCoursesToSyncState.withLock(\.handler) } + set { showCoursesToSyncState.withLock { $0.handler = newValue } } + } + public func showCoursesToSync() { + let showCoursesToSyncHandler = showCoursesToSyncState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showCoursesToSyncHandler = showCoursesToSyncHandler { + showCoursesToSyncHandler() + } + + } + + private let showRegisterScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showRegisterScreenCallCount: Int { + return showRegisterScreenState.withLock(\.callCount) + } + public var showRegisterScreenHandler: (@Sendable (LogistrationSourceScreen) -> ())? { + get { showRegisterScreenState.withLock(\.handler) } + set { showRegisterScreenState.withLock { $0.handler = newValue } } + } + public func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { + let showRegisterScreenHandler = showRegisterScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showRegisterScreenHandler = showRegisterScreenHandler { + showRegisterScreenHandler(sourceScreen) + } + + } + + private let showVideoQualityViewState = MockoloMutex(MockoloHandlerState ()>()) + public var showVideoQualityViewCallCount: Int { + return showVideoQualityViewState.withLock(\.callCount) + } + public var showVideoQualityViewHandler: (@Sendable (SettingsViewModel) -> ())? { + get { showVideoQualityViewState.withLock(\.handler) } + set { showVideoQualityViewState.withLock { $0.handler = newValue } } + } + public func showVideoQualityView(viewModel: SettingsViewModel) { + let showVideoQualityViewHandler = showVideoQualityViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showVideoQualityViewHandler = showVideoQualityViewHandler { + showVideoQualityViewHandler(viewModel) + } + + } + + private let showVideoDownloadQualityViewState = MockoloMutex(MockoloHandlerState Void)?, CoreAnalytics) -> ()>()) + public var showVideoDownloadQualityViewCallCount: Int { + return showVideoDownloadQualityViewState.withLock(\.callCount) + } + public var showVideoDownloadQualityViewHandler: (@Sendable (DownloadQuality, ((DownloadQuality) -> Void)?, CoreAnalytics) -> ())? { + get { showVideoDownloadQualityViewState.withLock(\.handler) } + set { showVideoDownloadQualityViewState.withLock { $0.handler = newValue } } + } + public func showVideoDownloadQualityView(downloadQuality: DownloadQuality, didSelect: ((DownloadQuality) -> Void)?, analytics: CoreAnalytics) { + let showVideoDownloadQualityViewHandler = showVideoDownloadQualityViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showVideoDownloadQualityViewHandler = showVideoDownloadQualityViewHandler { + showVideoDownloadQualityViewHandler(downloadQuality, didSelect, analytics) + } + + } + + private let showForgotPasswordScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showForgotPasswordScreenCallCount: Int { + return showForgotPasswordScreenState.withLock(\.callCount) + } + public var showForgotPasswordScreenHandler: (@Sendable () -> ())? { + get { showForgotPasswordScreenState.withLock(\.handler) } + set { showForgotPasswordScreenState.withLock { $0.handler = newValue } } + } + public func showForgotPasswordScreen() { + let showForgotPasswordScreenHandler = showForgotPasswordScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showForgotPasswordScreenHandler = showForgotPasswordScreenHandler { + showForgotPasswordScreenHandler() + } + + } + + private let showDiscoveryScreenState = MockoloMutex(MockoloHandlerState ()>()) + public var showDiscoveryScreenCallCount: Int { + return showDiscoveryScreenState.withLock(\.callCount) + } + public var showDiscoveryScreenHandler: (@Sendable (String?, LogistrationSourceScreen) -> ())? { + get { showDiscoveryScreenState.withLock(\.handler) } + set { showDiscoveryScreenState.withLock { $0.handler = newValue } } + } + public func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { + let showDiscoveryScreenHandler = showDiscoveryScreenState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDiscoveryScreenHandler = showDiscoveryScreenHandler { + showDiscoveryScreenHandler(searchQuery, sourceScreen) + } + + } + + private let showWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showWebBrowserCallCount: Int { + return showWebBrowserState.withLock(\.callCount) + } + public var showWebBrowserHandler: (@Sendable (String, URL) -> ())? { + get { showWebBrowserState.withLock(\.handler) } + set { showWebBrowserState.withLock { $0.handler = newValue } } + } + public func showWebBrowser(title: String, url: URL) { + let showWebBrowserHandler = showWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showWebBrowserHandler = showWebBrowserHandler { + showWebBrowserHandler(title, url) + } + + } + + private let showDeleteProfileViewState = MockoloMutex(MockoloHandlerState ()>()) + public var showDeleteProfileViewCallCount: Int { + return showDeleteProfileViewState.withLock(\.callCount) + } + public var showDeleteProfileViewHandler: (@Sendable () -> ())? { + get { showDeleteProfileViewState.withLock(\.handler) } + set { showDeleteProfileViewState.withLock { $0.handler = newValue } } + } + public func showDeleteProfileView() { + let showDeleteProfileViewHandler = showDeleteProfileViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showDeleteProfileViewHandler = showDeleteProfileViewHandler { + showDeleteProfileViewHandler() + } + + } + + private let showSSOWebBrowserState = MockoloMutex(MockoloHandlerState ()>()) + public var showSSOWebBrowserCallCount: Int { + return showSSOWebBrowserState.withLock(\.callCount) + } + public var showSSOWebBrowserHandler: (@Sendable (String) -> ())? { + get { showSSOWebBrowserState.withLock(\.handler) } + set { showSSOWebBrowserState.withLock { $0.handler = newValue } } + } + public func showSSOWebBrowser(title: String) { + let showSSOWebBrowserHandler = showSSOWebBrowserState.withLock { state in + state.callCount += 1 + return state.handler + } + if let showSSOWebBrowserHandler = showSSOWebBrowserHandler { + showSSOWebBrowserHandler(title) + } + + } + + private let presentAlertState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, AlertViewType) -> ()>()) + public var presentAlertCallCount: Int { + return presentAlertState.withLock(\.callCount) + } + public var presentAlertHandler: (@Sendable (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> ())? { + get { presentAlertState.withLock(\.handler) } + set { presentAlertState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { + let presentAlertHandler = presentAlertState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertHandler = presentAlertHandler { + presentAlertHandler(alertTitle, alertMessage, positiveAction, onCloseTapped, firstButtonTapped, type) + } + + } + + private let presentAlertAlertTitleState = MockoloMutex(MockoloHandlerState Void, @escaping () -> Void, @escaping () -> Void) -> ()>()) + public var presentAlertAlertTitleCallCount: Int { + return presentAlertAlertTitleState.withLock(\.callCount) + } + public var presentAlertAlertTitleHandler: (@Sendable (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> ())? { + get { presentAlertAlertTitleState.withLock(\.handler) } + set { presentAlertAlertTitleState.withLock { $0.handler = newValue } } + } + public func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { + let presentAlertAlertTitleHandler = presentAlertAlertTitleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentAlertAlertTitleHandler = presentAlertAlertTitleHandler { + presentAlertAlertTitleHandler(alertTitle, alertMessage, nextSectionName, action, image, onCloseTapped, firstButtonTapped, nextSectionTapped) + } + + } + + private let presentViewState = MockoloMutex(MockoloHandlerState Void)?) -> ()>()) + public var presentViewCallCount: Int { + return presentViewState.withLock(\.callCount) + } + public var presentViewHandler: (@Sendable (UIModalTransitionStyle, any View, (() -> Void)?) -> ())? { + get { presentViewState.withLock(\.handler) } + set { presentViewState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { + let presentViewHandler = presentViewState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewHandler = presentViewHandler { + presentViewHandler(transitionStyle, view, completion) + } + + } + + private let presentViewTransitionStyleState = MockoloMutex(MockoloHandlerState any View) -> ()>()) + public var presentViewTransitionStyleCallCount: Int { + return presentViewTransitionStyleState.withLock(\.callCount) + } + public var presentViewTransitionStyleHandler: (@Sendable (UIModalTransitionStyle, Bool, () -> any View) -> ())? { + get { presentViewTransitionStyleState.withLock(\.handler) } + set { presentViewTransitionStyleState.withLock { $0.handler = newValue } } + } + public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { + let presentViewTransitionStyleHandler = presentViewTransitionStyleState.withLock { state in + state.callCount += 1 + return state.handler + } + if let presentViewTransitionStyleHandler = presentViewTransitionStyleHandler { + presentViewTransitionStyleHandler(transitionStyle, animated, content) + } + + } +} + +public final class ProfileStorageMock: ProfileStorage, @unchecked Sendable { + public init() { } + public init(userProfile: DataLayer.UserProfile? = nil, useRelativeDates: Bool = false, calendarSettings: CalendarSettings? = nil, hideInactiveCourses: Bool? = nil, lastLoginUsername: String? = nil, lastCalendarName: String? = nil, lastCalendarUpdateDate: Date? = nil, firstCalendarUpdate: Bool? = nil) { + self.userProfile = userProfile + self.useRelativeDates = useRelativeDates + self.calendarSettings = calendarSettings + self.hideInactiveCourses = hideInactiveCourses + self.lastLoginUsername = lastLoginUsername + self.lastCalendarName = lastCalendarName + self.lastCalendarUpdateDate = lastCalendarUpdateDate + self.firstCalendarUpdate = firstCalendarUpdate + } + + + public private(set) var userProfileSetCallCount = 0 + public var userProfile: DataLayer.UserProfile? = nil { didSet { userProfileSetCallCount += 1 } } + + public private(set) var useRelativeDatesSetCallCount = 0 + public var useRelativeDates: Bool = false { didSet { useRelativeDatesSetCallCount += 1 } } + + public private(set) var calendarSettingsSetCallCount = 0 + public var calendarSettings: CalendarSettings? = nil { didSet { calendarSettingsSetCallCount += 1 } } + + public private(set) var hideInactiveCoursesSetCallCount = 0 + public var hideInactiveCourses: Bool? = nil { didSet { hideInactiveCoursesSetCallCount += 1 } } + + public private(set) var lastLoginUsernameSetCallCount = 0 + public var lastLoginUsername: String? = nil { didSet { lastLoginUsernameSetCallCount += 1 } } + + public private(set) var lastCalendarNameSetCallCount = 0 + public var lastCalendarName: String? = nil { didSet { lastCalendarNameSetCallCount += 1 } } + + public private(set) var lastCalendarUpdateDateSetCallCount = 0 + public var lastCalendarUpdateDate: Date? = nil { didSet { lastCalendarUpdateDateSetCallCount += 1 } } + + public private(set) var firstCalendarUpdateSetCallCount = 0 + public var firstCalendarUpdate: Bool? = nil { didSet { firstCalendarUpdateSetCallCount += 1 } } +} + +public final class ProfileInteractorProtocolMock: ProfileInteractorProtocol, @unchecked Sendable { + public init() { } + + + private let getUserProfileState = MockoloMutex(MockoloHandlerState UserProfile>()) + public var getUserProfileCallCount: Int { + return getUserProfileState.withLock(\.callCount) + } + public var getUserProfileHandler: (@Sendable (String) async throws -> UserProfile)? { + get { getUserProfileState.withLock(\.handler) } + set { getUserProfileState.withLock { $0.handler = newValue } } + } + public func getUserProfile(username: String) async throws -> UserProfile { + let getUserProfileHandler = getUserProfileState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getUserProfileHandler = getUserProfileHandler { + return try await getUserProfileHandler(username) + } + fatalError("getUserProfileHandler returns can't have a default value thus its handler must be set") + } + + private let getMyProfileState = MockoloMutex(MockoloHandlerState UserProfile>()) + public var getMyProfileCallCount: Int { + return getMyProfileState.withLock(\.callCount) + } + public var getMyProfileHandler: (@Sendable () async throws -> UserProfile)? { + get { getMyProfileState.withLock(\.handler) } + set { getMyProfileState.withLock { $0.handler = newValue } } + } + public func getMyProfile() async throws -> UserProfile { + let getMyProfileHandler = getMyProfileState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getMyProfileHandler = getMyProfileHandler { + return try await getMyProfileHandler() + } + fatalError("getMyProfileHandler returns can't have a default value thus its handler must be set") + } + + private let getMyProfileOfflineState = MockoloMutex(MockoloHandlerState UserProfile?>()) + public var getMyProfileOfflineCallCount: Int { + return getMyProfileOfflineState.withLock(\.callCount) + } + public var getMyProfileOfflineHandler: (@Sendable () async -> UserProfile?)? { + get { getMyProfileOfflineState.withLock(\.handler) } + set { getMyProfileOfflineState.withLock { $0.handler = newValue } } + } + public func getMyProfileOffline() async -> UserProfile? { + let getMyProfileOfflineHandler = getMyProfileOfflineState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getMyProfileOfflineHandler = getMyProfileOfflineHandler { + return await getMyProfileOfflineHandler() + } + return nil + } + + private let logOutState = MockoloMutex(MockoloHandlerState ()>()) + public var logOutCallCount: Int { + return logOutState.withLock(\.callCount) + } + public var logOutHandler: (@Sendable () async throws -> ())? { + get { logOutState.withLock(\.handler) } + set { logOutState.withLock { $0.handler = newValue } } + } + public func logOut() async throws { + let logOutHandler = logOutState.withLock { state in + state.callCount += 1 + return state.handler + } + if let logOutHandler = logOutHandler { + try await logOutHandler() + } + + } + + private let getSpokenLanguagesState = MockoloMutex(MockoloHandlerState [PickerFields.Option]>()) + public var getSpokenLanguagesCallCount: Int { + return getSpokenLanguagesState.withLock(\.callCount) + } + public var getSpokenLanguagesHandler: (@Sendable () -> [PickerFields.Option])? { + get { getSpokenLanguagesState.withLock(\.handler) } + set { getSpokenLanguagesState.withLock { $0.handler = newValue } } + } + public func getSpokenLanguages() -> [PickerFields.Option] { + let getSpokenLanguagesHandler = getSpokenLanguagesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getSpokenLanguagesHandler = getSpokenLanguagesHandler { + return getSpokenLanguagesHandler() + } + return [PickerFields.Option]() + } + + private let getCountriesState = MockoloMutex(MockoloHandlerState [PickerFields.Option]>()) + public var getCountriesCallCount: Int { + return getCountriesState.withLock(\.callCount) + } + public var getCountriesHandler: (@Sendable () -> [PickerFields.Option])? { + get { getCountriesState.withLock(\.handler) } + set { getCountriesState.withLock { $0.handler = newValue } } + } + public func getCountries() -> [PickerFields.Option] { + let getCountriesHandler = getCountriesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCountriesHandler = getCountriesHandler { + return getCountriesHandler() + } + return [PickerFields.Option]() + } + + private let uploadProfilePictureState = MockoloMutex(MockoloHandlerState ()>()) + public var uploadProfilePictureCallCount: Int { + return uploadProfilePictureState.withLock(\.callCount) + } + public var uploadProfilePictureHandler: (@Sendable (Data) async throws -> ())? { + get { uploadProfilePictureState.withLock(\.handler) } + set { uploadProfilePictureState.withLock { $0.handler = newValue } } + } + public func uploadProfilePicture(pictureData: Data) async throws { + let uploadProfilePictureHandler = uploadProfilePictureState.withLock { state in + state.callCount += 1 + return state.handler + } + if let uploadProfilePictureHandler = uploadProfilePictureHandler { + try await uploadProfilePictureHandler(pictureData) + } + + } + + private let deleteProfilePictureState = MockoloMutex(MockoloHandlerState Bool>()) + public var deleteProfilePictureCallCount: Int { + return deleteProfilePictureState.withLock(\.callCount) + } + public var deleteProfilePictureHandler: (@Sendable () async throws -> Bool)? { + get { deleteProfilePictureState.withLock(\.handler) } + set { deleteProfilePictureState.withLock { $0.handler = newValue } } + } + public func deleteProfilePicture() async throws -> Bool { + let deleteProfilePictureHandler = deleteProfilePictureState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteProfilePictureHandler = deleteProfilePictureHandler { + return try await deleteProfilePictureHandler() + } + return false + } + + private let updateUserProfileState = MockoloMutex(MockoloHandlerState UserProfile>()) + public var updateUserProfileCallCount: Int { + return updateUserProfileState.withLock(\.callCount) + } + public var updateUserProfileHandler: (@Sendable ([String: any Any & Sendable]) async throws -> UserProfile)? { + get { updateUserProfileState.withLock(\.handler) } + set { updateUserProfileState.withLock { $0.handler = newValue } } + } + public func updateUserProfile(parameters: [String: any Any & Sendable]) async throws -> UserProfile { + let updateUserProfileHandler = updateUserProfileState.withLock { state in + state.callCount += 1 + return state.handler + } + if let updateUserProfileHandler = updateUserProfileHandler { + return try await updateUserProfileHandler(parameters) + } + fatalError("updateUserProfileHandler returns can't have a default value thus its handler must be set") + } + + private let deleteAccountState = MockoloMutex(MockoloHandlerState Bool>()) + public var deleteAccountCallCount: Int { + return deleteAccountState.withLock(\.callCount) + } + public var deleteAccountHandler: (@Sendable (String) async throws -> Bool)? { + get { deleteAccountState.withLock(\.handler) } + set { deleteAccountState.withLock { $0.handler = newValue } } + } + public func deleteAccount(password: String) async throws -> Bool { + let deleteAccountHandler = deleteAccountState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAccountHandler = deleteAccountHandler { + return try await deleteAccountHandler(password) + } + return false + } + + private let getSettingsState = MockoloMutex(MockoloHandlerState UserSettings>()) + public var getSettingsCallCount: Int { + return getSettingsState.withLock(\.callCount) + } + public var getSettingsHandler: (@Sendable () -> UserSettings)? { + get { getSettingsState.withLock(\.handler) } + set { getSettingsState.withLock { $0.handler = newValue } } + } + public func getSettings() -> UserSettings { + let getSettingsHandler = getSettingsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getSettingsHandler = getSettingsHandler { + return getSettingsHandler() + } + fatalError("getSettingsHandler returns can't have a default value thus its handler must be set") + } + + private let saveSettingsState = MockoloMutex(MockoloHandlerState ()>()) + public var saveSettingsCallCount: Int { + return saveSettingsState.withLock(\.callCount) + } + public var saveSettingsHandler: (@Sendable (UserSettings) async -> ())? { + get { saveSettingsState.withLock(\.handler) } + set { saveSettingsState.withLock { $0.handler = newValue } } + } + public func saveSettings(_ settings: UserSettings) async { + let saveSettingsHandler = saveSettingsState.withLock { state in + state.callCount += 1 + return state.handler + } + if let saveSettingsHandler = saveSettingsHandler { + await saveSettingsHandler(settings) + } + + } + + private let enrollmentsStatusState = MockoloMutex(MockoloHandlerState [CourseForSync]>()) + public var enrollmentsStatusCallCount: Int { + return enrollmentsStatusState.withLock(\.callCount) + } + public var enrollmentsStatusHandler: (@Sendable () async throws -> [CourseForSync])? { + get { enrollmentsStatusState.withLock(\.handler) } + set { enrollmentsStatusState.withLock { $0.handler = newValue } } + } + public func enrollmentsStatus() async throws -> [CourseForSync] { + let enrollmentsStatusHandler = enrollmentsStatusState.withLock { state in + state.callCount += 1 + return state.handler + } + if let enrollmentsStatusHandler = enrollmentsStatusHandler { + return try await enrollmentsStatusHandler() + } + return [CourseForSync]() + } + + private let getCourseDatesState = MockoloMutex(MockoloHandlerState CourseDates>()) + public var getCourseDatesCallCount: Int { + return getCourseDatesState.withLock(\.callCount) + } + public var getCourseDatesHandler: (@Sendable (String) async throws -> CourseDates)? { + get { getCourseDatesState.withLock(\.handler) } + set { getCourseDatesState.withLock { $0.handler = newValue } } + } + public func getCourseDates(courseID: String) async throws -> CourseDates { + let getCourseDatesHandler = getCourseDatesState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCourseDatesHandler = getCourseDatesHandler { + return try await getCourseDatesHandler(courseID) + } + fatalError("getCourseDatesHandler returns can't have a default value thus its handler must be set") + } +} + +public final class ProfileAnalyticsMock: ProfileAnalytics { + public init() { } + + + public private(set) var profileEditClickedCallCount = 0 + public var profileEditClickedHandler: (() -> ())? + public func profileEditClicked() { + profileEditClickedCallCount += 1 + if let profileEditClickedHandler = profileEditClickedHandler { + profileEditClickedHandler() + } + + } + + public private(set) var profileSwitchCallCount = 0 + public var profileSwitchHandler: ((String) -> ())? + public func profileSwitch(action: String) { + profileSwitchCallCount += 1 + if let profileSwitchHandler = profileSwitchHandler { + profileSwitchHandler(action) + } + + } + + public private(set) var profileEditDoneClickedCallCount = 0 + public var profileEditDoneClickedHandler: (() -> ())? + public func profileEditDoneClicked() { + profileEditDoneClickedCallCount += 1 + if let profileEditDoneClickedHandler = profileEditDoneClickedHandler { + profileEditDoneClickedHandler() + } + + } + + public private(set) var profileDeleteAccountClickedCallCount = 0 + public var profileDeleteAccountClickedHandler: (() -> ())? + public func profileDeleteAccountClicked() { + profileDeleteAccountClickedCallCount += 1 + if let profileDeleteAccountClickedHandler = profileDeleteAccountClickedHandler { + profileDeleteAccountClickedHandler() + } + + } + + public private(set) var profileVideoSettingsClickedCallCount = 0 + public var profileVideoSettingsClickedHandler: (() -> ())? + public func profileVideoSettingsClicked() { + profileVideoSettingsClickedCallCount += 1 + if let profileVideoSettingsClickedHandler = profileVideoSettingsClickedHandler { + profileVideoSettingsClickedHandler() + } + + } + + public private(set) var privacyPolicyClickedCallCount = 0 + public var privacyPolicyClickedHandler: (() -> ())? + public func privacyPolicyClicked() { + privacyPolicyClickedCallCount += 1 + if let privacyPolicyClickedHandler = privacyPolicyClickedHandler { + privacyPolicyClickedHandler() + } + + } + + public private(set) var cookiePolicyClickedCallCount = 0 + public var cookiePolicyClickedHandler: (() -> ())? + public func cookiePolicyClicked() { + cookiePolicyClickedCallCount += 1 + if let cookiePolicyClickedHandler = cookiePolicyClickedHandler { + cookiePolicyClickedHandler() + } + + } + + public private(set) var emailSupportClickedCallCount = 0 + public var emailSupportClickedHandler: (() -> ())? + public func emailSupportClicked() { + emailSupportClickedCallCount += 1 + if let emailSupportClickedHandler = emailSupportClickedHandler { + emailSupportClickedHandler() + } + + } + + public private(set) var faqClickedCallCount = 0 + public var faqClickedHandler: (() -> ())? + public func faqClicked() { + faqClickedCallCount += 1 + if let faqClickedHandler = faqClickedHandler { + faqClickedHandler() + } + + } + + public private(set) var tosClickedCallCount = 0 + public var tosClickedHandler: (() -> ())? + public func tosClicked() { + tosClickedCallCount += 1 + if let tosClickedHandler = tosClickedHandler { + tosClickedHandler() + } + + } + + public private(set) var dataSellClickedCallCount = 0 + public var dataSellClickedHandler: (() -> ())? + public func dataSellClicked() { + dataSellClickedCallCount += 1 + if let dataSellClickedHandler = dataSellClickedHandler { + dataSellClickedHandler() + } + + } + + public private(set) var userLogoutCallCount = 0 + public var userLogoutHandler: ((Bool) -> ())? + public func userLogout(force: Bool) { + userLogoutCallCount += 1 + if let userLogoutHandler = userLogoutHandler { + userLogoutHandler(force) + } + + } + + public private(set) var profileWifiToggleCallCount = 0 + public var profileWifiToggleHandler: ((String) -> ())? + public func profileWifiToggle(action: String) { + profileWifiToggleCallCount += 1 + if let profileWifiToggleHandler = profileWifiToggleHandler { + profileWifiToggleHandler(action) + } + + } + + public private(set) var profileUserDeleteAccountClickedCallCount = 0 + public var profileUserDeleteAccountClickedHandler: (() -> ())? + public func profileUserDeleteAccountClicked() { + profileUserDeleteAccountClickedCallCount += 1 + if let profileUserDeleteAccountClickedHandler = profileUserDeleteAccountClickedHandler { + profileUserDeleteAccountClickedHandler() + } + + } + + public private(set) var profileDeleteAccountSuccessCallCount = 0 + public var profileDeleteAccountSuccessHandler: ((Bool) -> ())? + public func profileDeleteAccountSuccess(success: Bool) { + profileDeleteAccountSuccessCallCount += 1 + if let profileDeleteAccountSuccessHandler = profileDeleteAccountSuccessHandler { + profileDeleteAccountSuccessHandler(success) + } + + } + + public private(set) var profileTrackEventCallCount = 0 + public var profileTrackEventHandler: ((AnalyticsEvent, EventBIValue) -> ())? + public func profileTrackEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { + profileTrackEventCallCount += 1 + if let profileTrackEventHandler = profileTrackEventHandler { + profileTrackEventHandler(event, biValue) + } + + } + + public private(set) var profileScreenEventCallCount = 0 + public var profileScreenEventHandler: ((AnalyticsEvent, EventBIValue) -> ())? + public func profileScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { + profileScreenEventCallCount += 1 + if let profileScreenEventHandler = profileScreenEventHandler { + profileScreenEventHandler(event, biValue) + } + + } +} + +public final class ConnectivityProtocolMock: ConnectivityProtocol, @unchecked Sendable { + public init() { } + public init(isInternetAvaliable: Bool = false, isMobileData: Bool = false) { + self.isInternetAvaliable = isInternetAvaliable + self.isMobileData = isMobileData + } + + + + public var isInternetAvaliable: Bool = false + + + public var isMobileData: Bool = false + + + private var _internetReachableSubject: CurrentValueSubject! + public var internetReachableSubject: CurrentValueSubject { + get { return _internetReachableSubject } + set { _internetReachableSubject = newValue } + } +} + +public final class DownloadManagerProtocolMock: DownloadManagerProtocol, @unchecked Sendable { + public init() { } + + + private let getCurrentDownloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var getCurrentDownloadTaskCallCount: Int { + return getCurrentDownloadTaskState.withLock(\.callCount) + } + public var getCurrentDownloadTaskHandler: (@Sendable () async -> DownloadDataTask?)? { + get { getCurrentDownloadTaskState.withLock(\.handler) } + set { getCurrentDownloadTaskState.withLock { $0.handler = newValue } } + } + public func getCurrentDownloadTask() async -> DownloadDataTask? { + let getCurrentDownloadTaskHandler = getCurrentDownloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getCurrentDownloadTaskHandler = getCurrentDownloadTaskHandler { + return await getCurrentDownloadTaskHandler() + } + return nil + } + + private let eventPublisherState = MockoloMutex(MockoloHandlerState AnyPublisher>()) + public var eventPublisherCallCount: Int { + return eventPublisherState.withLock(\.callCount) + } + public var eventPublisherHandler: (@Sendable () -> AnyPublisher)? { + get { eventPublisherState.withLock(\.handler) } + set { eventPublisherState.withLock { $0.handler = newValue } } + } + public func eventPublisher() -> AnyPublisher { + let eventPublisherHandler = eventPublisherState.withLock { state in + state.callCount += 1 + return state.handler + } + if let eventPublisherHandler = eventPublisherHandler { + return eventPublisherHandler() + } + fatalError("eventPublisherHandler returns can't have a default value thus its handler must be set") + } + + private let addToDownloadQueueState = MockoloMutex(MockoloHandlerState ()>()) + public var addToDownloadQueueCallCount: Int { + return addToDownloadQueueState.withLock(\.callCount) + } + public var addToDownloadQueueHandler: (@Sendable ([CourseBlock]) async throws -> ())? { + get { addToDownloadQueueState.withLock(\.handler) } + set { addToDownloadQueueState.withLock { $0.handler = newValue } } + } + public func addToDownloadQueue(blocks: [CourseBlock]) async throws { + let addToDownloadQueueHandler = addToDownloadQueueState.withLock { state in + state.callCount += 1 + return state.handler + } + if let addToDownloadQueueHandler = addToDownloadQueueHandler { + try await addToDownloadQueueHandler(blocks) + } + + } + + private let getDownloadTasksState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksCallCount: Int { + return getDownloadTasksState.withLock(\.callCount) + } + public var getDownloadTasksHandler: (@Sendable () async -> [DownloadDataTask])? { + get { getDownloadTasksState.withLock(\.handler) } + set { getDownloadTasksState.withLock { $0.handler = newValue } } + } + public func getDownloadTasks() async -> [DownloadDataTask] { + let getDownloadTasksHandler = getDownloadTasksState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksHandler = getDownloadTasksHandler { + return await getDownloadTasksHandler() + } + return [DownloadDataTask]() + } + + private let getDownloadTasksForCourseState = MockoloMutex(MockoloHandlerState [DownloadDataTask]>()) + public var getDownloadTasksForCourseCallCount: Int { + return getDownloadTasksForCourseState.withLock(\.callCount) + } + public var getDownloadTasksForCourseHandler: (@Sendable (String) async -> [DownloadDataTask])? { + get { getDownloadTasksForCourseState.withLock(\.handler) } + set { getDownloadTasksForCourseState.withLock { $0.handler = newValue } } + } + public func getDownloadTasksForCourse(_ courseId: String) async -> [DownloadDataTask] { + let getDownloadTasksForCourseHandler = getDownloadTasksForCourseState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getDownloadTasksForCourseHandler = getDownloadTasksForCourseHandler { + return await getDownloadTasksForCourseHandler(courseId) + } + return [DownloadDataTask]() + } + + private let cancelDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCallCount: Int { + return cancelDownloadingState.withLock(\.callCount) + } + public var cancelDownloadingHandler: (@Sendable (String, [CourseBlock]) async throws -> ())? { + get { cancelDownloadingState.withLock(\.handler) } + set { cancelDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String, blocks: [CourseBlock]) async throws { + let cancelDownloadingHandler = cancelDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingHandler = cancelDownloadingHandler { + try await cancelDownloadingHandler(courseId, blocks) + } + + } + + private let cancelDownloadingTaskState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingTaskCallCount: Int { + return cancelDownloadingTaskState.withLock(\.callCount) + } + public var cancelDownloadingTaskHandler: (@Sendable (DownloadDataTask) async throws -> ())? { + get { cancelDownloadingTaskState.withLock(\.handler) } + set { cancelDownloadingTaskState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(task: DownloadDataTask) async throws { + let cancelDownloadingTaskHandler = cancelDownloadingTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingTaskHandler = cancelDownloadingTaskHandler { + try await cancelDownloadingTaskHandler(task) + } + + } + + private let cancelDownloadingCourseIdState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelDownloadingCourseIdCallCount: Int { + return cancelDownloadingCourseIdState.withLock(\.callCount) + } + public var cancelDownloadingCourseIdHandler: (@Sendable (String) async throws -> ())? { + get { cancelDownloadingCourseIdState.withLock(\.handler) } + set { cancelDownloadingCourseIdState.withLock { $0.handler = newValue } } + } + public func cancelDownloading(courseId: String) async throws { + let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelDownloadingCourseIdHandler = cancelDownloadingCourseIdHandler { + try await cancelDownloadingCourseIdHandler(courseId) + } + + } + + private let cancelAllDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var cancelAllDownloadingCallCount: Int { + return cancelAllDownloadingState.withLock(\.callCount) + } + public var cancelAllDownloadingHandler: (@Sendable () async throws -> ())? { + get { cancelAllDownloadingState.withLock(\.handler) } + set { cancelAllDownloadingState.withLock { $0.handler = newValue } } + } + public func cancelAllDownloading() async throws { + let cancelAllDownloadingHandler = cancelAllDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let cancelAllDownloadingHandler = cancelAllDownloadingHandler { + try await cancelAllDownloadingHandler() + } + + } + + private let deleteAllState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteAllCallCount: Int { + return deleteAllState.withLock(\.callCount) + } + public var deleteAllHandler: (@Sendable () async -> ())? { + get { deleteAllState.withLock(\.handler) } + set { deleteAllState.withLock { $0.handler = newValue } } + } + public func deleteAll() async { + let deleteAllHandler = deleteAllState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteAllHandler = deleteAllHandler { + await deleteAllHandler() + } + + } + + private let fileUrlState = MockoloMutex(MockoloHandlerState URL?>()) + public var fileUrlCallCount: Int { + return fileUrlState.withLock(\.callCount) + } + public var fileUrlHandler: (@Sendable (String) async -> URL?)? { + get { fileUrlState.withLock(\.handler) } + set { fileUrlState.withLock { $0.handler = newValue } } + } + public func fileUrl(for blockId: String) async -> URL? { + let fileUrlHandler = fileUrlState.withLock { state in + state.callCount += 1 + return state.handler + } + if let fileUrlHandler = fileUrlHandler { + return await fileUrlHandler(blockId) + } + return nil + } + + private let resumeDownloadingState = MockoloMutex(MockoloHandlerState ()>()) + public var resumeDownloadingCallCount: Int { + return resumeDownloadingState.withLock(\.callCount) + } + public var resumeDownloadingHandler: (@Sendable () async throws -> ())? { + get { resumeDownloadingState.withLock(\.handler) } + set { resumeDownloadingState.withLock { $0.handler = newValue } } + } + public func resumeDownloading() async throws { + let resumeDownloadingHandler = resumeDownloadingState.withLock { state in + state.callCount += 1 + return state.handler + } + if let resumeDownloadingHandler = resumeDownloadingHandler { + try await resumeDownloadingHandler() + } + + } + + private let isLargeVideosSizeState = MockoloMutex(MockoloHandlerState Bool>()) + public var isLargeVideosSizeCallCount: Int { + return isLargeVideosSizeState.withLock(\.callCount) + } + public var isLargeVideosSizeHandler: (@Sendable ([CourseBlock]) async -> Bool)? { + get { isLargeVideosSizeState.withLock(\.handler) } + set { isLargeVideosSizeState.withLock { $0.handler = newValue } } + } + public func isLargeVideosSize(blocks: [CourseBlock]) async -> Bool { + let isLargeVideosSizeHandler = isLargeVideosSizeState.withLock { state in + state.callCount += 1 + return state.handler + } + if let isLargeVideosSizeHandler = isLargeVideosSizeHandler { + return await isLargeVideosSizeHandler(blocks) + } + return false + } + + private let removeAppSupportDirectoryUnusedContentState = MockoloMutex(MockoloHandlerState ()>()) + public var removeAppSupportDirectoryUnusedContentCallCount: Int { + return removeAppSupportDirectoryUnusedContentState.withLock(\.callCount) + } + public var removeAppSupportDirectoryUnusedContentHandler: (@Sendable () -> ())? { + get { removeAppSupportDirectoryUnusedContentState.withLock(\.handler) } + set { removeAppSupportDirectoryUnusedContentState.withLock { $0.handler = newValue } } + } + public func removeAppSupportDirectoryUnusedContent() { + let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentState.withLock { state in + state.callCount += 1 + return state.handler + } + if let removeAppSupportDirectoryUnusedContentHandler = removeAppSupportDirectoryUnusedContentHandler { + removeAppSupportDirectoryUnusedContentHandler() + } + + } + + private let deleteState = MockoloMutex(MockoloHandlerState ()>()) + public var deleteCallCount: Int { + return deleteState.withLock(\.callCount) + } + public var deleteHandler: (@Sendable ([CourseBlock], String) async -> ())? { + get { deleteState.withLock(\.handler) } + set { deleteState.withLock { $0.handler = newValue } } + } + public func delete(blocks: [CourseBlock], courseId: String) async { + let deleteHandler = deleteState.withLock { state in + state.callCount += 1 + return state.handler + } + if let deleteHandler = deleteHandler { + await deleteHandler(blocks, courseId) + } + + } + + private let downloadTaskState = MockoloMutex(MockoloHandlerState DownloadDataTask?>()) + public var downloadTaskCallCount: Int { + return downloadTaskState.withLock(\.callCount) + } + public var downloadTaskHandler: (@Sendable (String) async -> DownloadDataTask?)? { + get { downloadTaskState.withLock(\.handler) } + set { downloadTaskState.withLock { $0.handler = newValue } } + } + public func downloadTask(for blockId: String) async -> DownloadDataTask? { + let downloadTaskHandler = downloadTaskState.withLock { state in + state.callCount += 1 + return state.handler + } + if let downloadTaskHandler = downloadTaskHandler { + return await downloadTaskHandler(blockId) + } + return nil + } + + private let getFreeDiskSpaceState = MockoloMutex(MockoloHandlerState Int?>()) + public var getFreeDiskSpaceCallCount: Int { + return getFreeDiskSpaceState.withLock(\.callCount) + } + public var getFreeDiskSpaceHandler: (@Sendable () -> Int?)? { + get { getFreeDiskSpaceState.withLock(\.handler) } + set { getFreeDiskSpaceState.withLock { $0.handler = newValue } } + } + public func getFreeDiskSpace() -> Int? { + let getFreeDiskSpaceHandler = getFreeDiskSpaceState.withLock { state in + state.callCount += 1 + return state.handler + } + if let getFreeDiskSpaceHandler = getFreeDiskSpaceHandler { + return getFreeDiskSpaceHandler() + } + return nil + } +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { + print("At \(function), the captured arguments are not Sendable, it is not concurrency-safe.") +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { +} + +/// Will be replaced to `Synchronization.Mutex` in future. +fileprivate final class MockoloMutex: @unchecked Sendable { + private let lock = NSLock() + private var value: Value + init(_ initialValue: Value) { + self.value = initialValue + } +#if compiler(>=6.0) + borrowing func withLock(_ body: (inout sending Value) throws(E) -> Result) throws(E) -> sending Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#else + func withLock(_ body: (inout Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#endif +} + +fileprivate struct MockoloUnsafeTransfer: @unchecked Sendable { + var value: Value + init(_ value: Value) { + self.value = value + } +} + +fileprivate struct MockoloHandlerState { + var argValues: [MockoloUnsafeTransfer] = [] + var handler: Handler? = nil + var callCount: Int = 0 +} + diff --git a/Profile/ProfileTests/Presentation/DeleteAccount/DeleteAccountViewModelTests.swift b/Profile/ProfileTests/Presentation/DeleteAccount/DeleteAccountViewModelTests.swift index d825f3ace..cda29e2fd 100644 --- a/Profile/ProfileTests/Presentation/DeleteAccount/DeleteAccountViewModelTests.swift +++ b/Profile/ProfileTests/Presentation/DeleteAccount/DeleteAccountViewModelTests.swift @@ -2,10 +2,9 @@ // DeleteAccountViewModelTests.swift // ProfileTests // -// Created by  Stepanok Ivan on 07.03.2023. +// Created by Stepanok Ivan on 07.03.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Profile @@ -15,118 +14,129 @@ import SwiftUI @MainActor final class DeleteAccountViewModelTests: XCTestCase { - + func testDeletingAccountSuccess() async throws { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let connectivity = ConnectivityProtocolMock() + let analytics = ProfileAnalyticsMock() + + interactor.deleteAccountHandler = { _ in true } + router.showLoginScreenHandler = { _ in } + let viewModel = DeleteAccountViewModel( interactor: interactor, router: router, connectivity: connectivity, - analytics: ProfileAnalyticsMock() + analytics: analytics ) - - Given(interactor, .deleteAccount(password: .any, willReturn: true)) - + try await viewModel.deleteAccount(password: "123") - - Verify(interactor, 1, .deleteAccount(password: .any)) - Verify(router, .showLoginScreen(sourceScreen: .any)) + + XCTAssertEqual(interactor.deleteAccountCallCount, 1) + XCTAssertEqual(router.showLoginScreenCallCount, 1) } - + func testDeletingAccountWrongPassword() async throws { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let connectivity = ConnectivityProtocolMock() + let analytics = ProfileAnalyticsMock() + + interactor.deleteAccountHandler = { _ in false } + let viewModel = DeleteAccountViewModel( interactor: interactor, router: router, connectivity: connectivity, - analytics: ProfileAnalyticsMock() + analytics: analytics ) - - Given(interactor, .deleteAccount(password: .any, willReturn: false)) - + try await viewModel.deleteAccount(password: "123") - - Verify(interactor, 1, .deleteAccount(password: .any)) - Verify(router, 0, .showLoginScreen(sourceScreen: .any)) - + + XCTAssertEqual(interactor.deleteAccountCallCount, 1) + XCTAssertEqual(router.showLoginScreenCallCount, 0) + XCTAssertTrue(viewModel.incorrectPassword) } - + func testDeletingUserAccountNotActivatedError() async throws { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let connectivity = ConnectivityProtocolMock() + let analytics = ProfileAnalyticsMock() + + let validationError = CustomValidationError(statusCode: 401, data: ["error_code": "user_not_active"]) + let error = AFError.responseValidationFailed( + reason: AFError.ResponseValidationFailureReason.customValidationFailed(error: validationError) + ) + + interactor.deleteAccountHandler = { _ in throw error } + let viewModel = DeleteAccountViewModel( interactor: interactor, router: router, connectivity: connectivity, - analytics: ProfileAnalyticsMock() + analytics: analytics ) - - let validationError = CustomValidationError(statusCode: 401, data: ["error_code": "user_not_active"]) - let error = AFError.responseValidationFailed( - reason: AFError.ResponseValidationFailureReason.customValidationFailed(error: validationError) - ) - - Given(interactor, .deleteAccount(password: .any, willThrow: error)) - + try await viewModel.deleteAccount(password: "123") - - Verify(interactor, 1, .deleteAccount(password: .any)) - Verify(router, 0, .showLoginScreen(sourceScreen: .any)) - + + XCTAssertEqual(interactor.deleteAccountCallCount, 1) + XCTAssertEqual(router.showLoginScreenCallCount, 0) + XCTAssertFalse(viewModel.incorrectPassword) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.userNotActive) } - + func testDeletingUserUnknownError() async throws { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let connectivity = ConnectivityProtocolMock() + let analytics = ProfileAnalyticsMock() + + interactor.deleteAccountHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + let viewModel = DeleteAccountViewModel( interactor: interactor, router: router, connectivity: connectivity, - analytics: ProfileAnalyticsMock() + analytics: analytics ) - - Given(interactor, .deleteAccount(password: .any, willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + try await viewModel.deleteAccount(password: "123") - - Verify(interactor, 1, .deleteAccount(password: .any)) - Verify(router, 0, .showLoginScreen(sourceScreen: .any)) - + + XCTAssertEqual(interactor.deleteAccountCallCount, 1) + XCTAssertEqual(router.showLoginScreenCallCount, 0) + XCTAssertFalse(viewModel.incorrectPassword) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) } - + func testDeletingUserNoInternetError() async throws { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let connectivity = ConnectivityProtocolMock() + let analytics = ProfileAnalyticsMock() + + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) + + interactor.deleteAccountHandler = { _ in throw noInternetError } + let viewModel = DeleteAccountViewModel( interactor: interactor, router: router, connectivity: connectivity, - analytics: ProfileAnalyticsMock() + analytics: analytics ) - - let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .deleteAccount(password: .any, willThrow: noInternetError)) - + try await viewModel.deleteAccount(password: "123") - - Verify(interactor, 1, .deleteAccount(password: .any)) - Verify(router, 0, .showLoginScreen(sourceScreen: .any)) - + + XCTAssertEqual(interactor.deleteAccountCallCount, 1) + XCTAssertEqual(router.showLoginScreenCallCount, 0) + XCTAssertFalse(viewModel.incorrectPassword) XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) diff --git a/Profile/ProfileTests/Presentation/EditProfile/EditProfileViewModelTests.swift b/Profile/ProfileTests/Presentation/EditProfile/EditProfileViewModelTests.swift index 2695fb84a..8e9e561e3 100644 --- a/Profile/ProfileTests/Presentation/EditProfile/EditProfileViewModelTests.swift +++ b/Profile/ProfileTests/Presentation/EditProfile/EditProfileViewModelTests.swift @@ -2,10 +2,9 @@ // EditProfileViewModelTests.swift // ProfileTests // -// Created by  Stepanok Ivan on 18.01.2023. +// Created by Stepanok Ivan on 18.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Profile @@ -15,7 +14,7 @@ import SwiftUI // swiftlint:disable type_body_length file_length @MainActor final class EditProfileViewModelTests: XCTestCase { - + func testResizeVerticalImage() async throws { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -32,28 +31,28 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: false, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userProfile, interactor: interactor, router: router, analytics: analytics ) - + let imageVertical = UIGraphicsImageRenderer(size: CGSize(width: 600, height: 800)).image { rendererContext in UIColor.red.setFill() rendererContext.fill(CGRect(origin: .zero, size: CGSize(width: 600, height: 800))) } - + viewModel.resizeImage(image: imageVertical, longSideSize: 500) - + XCTAssertNotNil(viewModel.inputImage) XCTAssertEqual(viewModel.inputImage?.size.height, 500) } - + func testResizeHorizontalImage() async throws { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -70,28 +69,28 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: false, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userProfile, interactor: interactor, router: router, analytics: analytics ) - + let imageHorizontal = UIGraphicsImageRenderer(size: CGSize(width: 800, height: 600)).image { rendererContext in UIColor.red.setFill() rendererContext.fill(CGRect(origin: .zero, size: CGSize(width: 800, height: 600))) } - + viewModel.resizeImage(image: imageHorizontal, longSideSize: 500) - + XCTAssertNotNil(viewModel.inputImage) XCTAssertEqual(viewModel.inputImage?.size.width, 500) } - + func testCheckChangesShortBiographyChanged() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -108,23 +107,23 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: false, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userProfile, interactor: interactor, router: router, analytics: analytics ) - + viewModel.profileChanges.shortBiography = "New bio" viewModel.checkChanges() - + XCTAssertTrue(viewModel.isChanged) } - + func testCheckChangesSpokenLanguageChanged() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -141,23 +140,23 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.spokenLanguageConfiguration.text = "Changed" viewModel.checkChanges() - + XCTAssertTrue(viewModel.isChanged) } - + func testCheckChangesBirthYearChanged() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -174,23 +173,23 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.yearsConfiguration.text = "Changed" viewModel.checkChanges() - + XCTAssertTrue(viewModel.isChanged) } - + func testCheckChangesAvatarChanged() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -207,23 +206,23 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.profileChanges.isAvatarChanged = true viewModel.checkChanges() - + XCTAssertTrue(viewModel.isChanged) } - + func testCheckChangesProfileTypeChanged() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -240,23 +239,23 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.profileChanges.profileType = .limited viewModel.checkChanges() - + XCTAssertTrue(viewModel.isChanged) } - + func testCheckChangesCountryChanged() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -273,23 +272,23 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.countriesConfiguration.text = "Changed" viewModel.checkChanges() - + XCTAssertTrue(viewModel.isChanged) } - + func testCheckProfileTypeNotYongUser() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -306,27 +305,27 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.profileChanges.profileType = viewModel.userModel.isFullProfile ? .full : .limited - + viewModel.yearsConfiguration.text = "1986" viewModel.checkProfileType() - + XCTAssertFalse(viewModel.isYongUser) XCTAssertTrue(viewModel.isEditable) XCTAssertTrue(viewModel.userModel.isFullProfile) } - + func testCheckProfileTypeIsYongerUser() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -343,27 +342,27 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let yearOfBirth10Years = Calendar.current.component(.year, from: Date()) - 10 - + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.yearsConfiguration.text = "\(yearOfBirth10Years - 1)" viewModel.checkProfileType() - + XCTAssertEqual(viewModel.profileChanges.profileType, .limited) XCTAssertTrue(viewModel.isYongUser) XCTAssertFalse(viewModel.isEditable) } - + func testCheckProfileTypeYearsConfigurationEmpty() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -380,25 +379,25 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: false, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.yearsConfiguration.text = "" viewModel.checkProfileType() - + XCTAssertEqual(viewModel.profileChanges.profileType, .limited) XCTAssertFalse(viewModel.isYongUser) XCTAssertFalse(viewModel.isEditable) } - + func testCheckProfileTypeYearsConfigurationEmptyYongUser() { let interactor = ProfileInteractorProtocolMock() @@ -416,26 +415,26 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: false, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.yearsConfiguration.text = "" viewModel.checkProfileType() - + XCTAssertEqual(viewModel.profileChanges.profileType, .limited) XCTAssertFalse(viewModel.isYongUser) XCTAssertFalse(viewModel.isEditable) XCTAssertTrue(viewModel.profileChanges.profileType == .limited) } - + func testSaveProfileUpdates() async { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -452,41 +451,41 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.countriesConfiguration.text = "USA" viewModel.spokenLanguageConfiguration.text = "EN" viewModel.yearsConfiguration.text = "1899" viewModel.profileChanges.shortBiography = "New bio" viewModel.profileChanges.isAvatarChanged = true - + viewModel.checkChanges() - + viewModel.inputImage = UIGraphicsImageRenderer(size: CGSize(width: 400, height: 400)).image { rendererContext in UIColor.red.setFill() rendererContext.fill(CGRect(origin: .zero, size: CGSize(width: 400, height: 400))) } - - Given(interactor, .uploadProfilePicture(pictureData: .any, willProduce: {_ in})) - Given(interactor, .updateUserProfile(parameters: .any, willReturn: viewModel.userModel)) - + + interactor.uploadProfilePictureHandler = { _ in } + interactor.updateUserProfileHandler = { _ in await viewModel.userModel } + await viewModel.saveProfileUpdates() - + await Task.yield() - - Verify(interactor, 1, .uploadProfilePicture(pictureData: .any)) - Verify(interactor, 1, .updateUserProfile(parameters: .any)) + + XCTAssertEqual(interactor.uploadProfilePictureCallCount, 1) + XCTAssertEqual(interactor.updateUserProfileCallCount, 1) } - + func testDeleteAvatarSuccess() async { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -503,35 +502,34 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.profileChanges.isAvatarDeleted = true - + viewModel.checkChanges() - + viewModel.inputImage = nil - - Given(interactor, .updateUserProfile(parameters: .any, willReturn: viewModel.userModel)) - Given(interactor, .deleteProfilePicture(willReturn: true)) - + + interactor.updateUserProfileHandler = { _ in await viewModel.userModel } + interactor.deleteProfilePictureHandler = { true } + await viewModel.saveProfileUpdates() - + await Task.yield() - -// Verify(interactor, 0, .uploadProfilePicture(pictureData: .any)) - Verify(interactor, 1, .deleteProfilePicture()) - Verify(interactor, 1, .updateUserProfile(parameters: .any)) + + XCTAssertEqual(interactor.deleteProfilePictureCallCount, 1) + XCTAssertEqual(interactor.updateUserProfileCallCount, 1) } - + func testSaveProfileUpdatesNoInternetError() async { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -548,47 +546,46 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.countriesConfiguration.text = "USA" viewModel.spokenLanguageConfiguration.text = "EN" viewModel.yearsConfiguration.text = "1899" viewModel.profileChanges.shortBiography = "New bio" viewModel.profileChanges.isAvatarChanged = true - + viewModel.checkChanges() - + viewModel.inputImage = UIGraphicsImageRenderer(size: CGSize(width: 400, height: 400)).image { rendererContext in UIColor.red.setFill() rendererContext.fill(CGRect(origin: .zero, size: CGSize(width: 400, height: 400))) } - + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .uploadProfilePicture(pictureData: .any, willProduce: {_ in})) - Given(interactor, .updateUserProfile(parameters: .any, - willThrow: noInternetError)) - + + interactor.uploadProfilePictureHandler = { _ in } + interactor.updateUserProfileHandler = { _ in throw noInternetError } + await viewModel.saveProfileUpdates() - - Verify(interactor, 0, .uploadProfilePicture(pictureData: .any)) - Verify(interactor, 1, .updateUserProfile(parameters: .any)) - + + XCTAssertEqual(interactor.uploadProfilePictureCallCount, 0) + XCTAssertEqual(interactor.updateUserProfileCallCount, 1) + XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.isChanged) } - + func testSaveProfileUpdatesUnknownError() async { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -605,47 +602,46 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.countriesConfiguration.text = "USA" viewModel.spokenLanguageConfiguration.text = "EN" viewModel.yearsConfiguration.text = "1899" viewModel.profileChanges.shortBiography = "New bio" viewModel.profileChanges.isAvatarChanged = true - + viewModel.checkChanges() - + viewModel.inputImage = UIGraphicsImageRenderer(size: CGSize(width: 400, height: 400)).image { rendererContext in UIColor.red.setFill() rendererContext.fill(CGRect(origin: .zero, size: CGSize(width: 400, height: 400))) } - - Given(interactor, .uploadProfilePicture(pictureData: .any, willProduce: {_ in})) - Given(interactor, .updateUserProfile(parameters: .any, - willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + + interactor.uploadProfilePictureHandler = { _ in } + interactor.updateUserProfileHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + await viewModel.saveProfileUpdates() - + await Task.yield() - - Verify(interactor, 0, .uploadProfilePicture(pictureData: .any)) - Verify(interactor, 1, .updateUserProfile(parameters: .any)) - + + XCTAssertEqual(interactor.uploadProfilePictureCallCount, 0) + XCTAssertEqual(interactor.updateUserProfileCallCount, 1) + XCTAssertTrue(viewModel.showError) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.isChanged) } - + func testBackButtonTapped() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -662,29 +658,24 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.profileChanges.isAvatarChanged = true viewModel.checkChanges() viewModel.backButtonTapped() - - Verify(router, 1, .presentAlert(alertTitle: .any, - alertMessage: .any, - positiveAction: .any, - onCloseTapped: .any, - firstButtonTapped: .any, - type: .any)) + + XCTAssertEqual(router.presentAlertCallCount, 1) } - + func testGenerateFieldConfigurationsFullProfile() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -701,23 +692,23 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.loadLocationsAndSpokenLanguages() - + XCTAssertTrue(viewModel.profileChanges.profileType == .full) XCTAssertEqual(viewModel.profileChanges.shortBiography, viewModel.userModel.shortBiography) } - + func testGenerateFieldConfigurationsLimitedProfile() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -734,22 +725,22 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: false, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.loadLocationsAndSpokenLanguages() - + XCTAssertTrue(viewModel.profileChanges.profileType == .limited) } - + func testLoadLocationsAndSpokenLanguages() async throws { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -766,30 +757,30 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: true, email: "" ) - + let languages = [ PickerFields.Option(value: "UA", name: "Ukraine", optionDefault: true), PickerFields.Option(value: "USA", name: "United States of America", optionDefault: false) ] - - Given(interactor, .getSpokenLanguages(willReturn: languages)) - Given(interactor, .getCountries(willReturn: languages)) - + + interactor.getSpokenLanguagesHandler = { languages } + interactor.getCountriesHandler = { languages } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.loadLocationsAndSpokenLanguages() - + await Task.yield() - - Verify(interactor, 1, .getSpokenLanguages()) - Verify(interactor, 1, .getCountries()) + + XCTAssertEqual(interactor.getSpokenLanguagesCallCount, 1) + XCTAssertEqual(interactor.getCountriesCallCount, 1) } - + func testTrackProfileDeleteAccountClicked() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -806,22 +797,22 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: false, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.trackProfileDeleteAccountClicked() - - Verify(analytics, 1, .profileDeleteAccountClicked()) + + XCTAssertEqual(analytics.profileDeleteAccountClickedCallCount, 1) } - + func testTrackProfileEditDoneClicked() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() @@ -838,19 +829,19 @@ final class EditProfileViewModelTests: XCTestCase { isFullProfile: false, email: "" ) - - Given(interactor, .getSpokenLanguages(willReturn: [])) - Given(interactor, .getCountries(willReturn: [])) - + + interactor.getSpokenLanguagesHandler = { [] } + interactor.getCountriesHandler = { [] } + let viewModel = EditProfileViewModel( userModel: userModel, interactor: interactor, router: router, analytics: analytics ) - + viewModel.trackProfileEditDoneClicked() - - Verify(analytics, 1, .profileEditDoneClicked()) + + XCTAssertEqual(analytics.profileEditDoneClickedCallCount, 1) } } diff --git a/Profile/ProfileTests/Presentation/Profile/ProfileViewModelTests.swift b/Profile/ProfileTests/Presentation/Profile/ProfileViewModelTests.swift index 72489d374..a8b8face6 100644 --- a/Profile/ProfileTests/Presentation/Profile/ProfileViewModelTests.swift +++ b/Profile/ProfileTests/Presentation/Profile/ProfileViewModelTests.swift @@ -2,10 +2,9 @@ // ProfileViewModelTests.swift // ProfileTests // -// Created by  Stepanok Ivan on 18.01.2023. +// Created by Stepanok Ivan on 18.01.2023. // -import SwiftyMocky import XCTest @testable import Core @testable import Profile @@ -14,15 +13,10 @@ import SwiftUI @MainActor final class ProfileViewModelTests: XCTestCase { - + func testGetUserProfileSuccess() async throws { let interactor = ProfileInteractorProtocolMock() - - let viewModel = UserProfileViewModel( - interactor: interactor, - username: "Steve" - ) - + let user = UserProfile( avatarUrl: "", name: "Steve", @@ -31,75 +25,71 @@ final class ProfileViewModelTests: XCTestCase { yearOfBirth: 2000, country: "Ua", shortBiography: "Bio", - isFullProfile: false, + isFullProfile: false, email: "" ) - - Given(interactor, .getUserProfile(username: .value("Steve"), willReturn: user)) - + + interactor.getUserProfileHandler = { _ in user } + + let viewModel = UserProfileViewModel( + interactor: interactor, + username: "Steve" + ) + await viewModel.getUserProfile() - - Verify(interactor, 1, .getUserProfile(username: .value("Steve"))) - + + XCTAssertEqual(interactor.getUserProfileCallCount, 1) XCTAssertEqual(viewModel.userModel, user) XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) } - + func testGetUserProfileNoInternetError() async throws { let interactor = ProfileInteractorProtocolMock() - + + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) + + interactor.getUserProfileHandler = { _ in throw noInternetError } + let viewModel = UserProfileViewModel( interactor: interactor, username: "Steve" ) - - let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(interactor, .getUserProfile(username: .value("Steve"), willThrow: noInternetError)) - + await viewModel.getUserProfile() - - Verify(interactor, 1, .getUserProfile(username: .value("Steve"))) - + + XCTAssertEqual(interactor.getUserProfileCallCount, 1) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) } - + func testGetUserProfileUnknownError() async throws { let interactor = ProfileInteractorProtocolMock() - + + interactor.getUserProfileHandler = { _ in throw NSError(domain: "error", code: -1, userInfo: nil) } + let viewModel = UserProfileViewModel( interactor: interactor, username: "Steve" ) - - Given(interactor, .getUserProfile(username: .value("Steve"), willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + await viewModel.getUserProfile() - - Verify(interactor, 1, .getUserProfile(username: .value("Steve"))) - + + XCTAssertEqual(interactor.getUserProfileCallCount, 1) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) } - + func testGetMyProfileSuccess() async throws { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let analytics = ProfileAnalyticsMock() let connectivity = ConnectivityProtocolMock() - let viewModel = ProfileViewModel( - interactor: interactor, - router: router, - analytics: analytics, - config: ConfigMock(), - connectivity: connectivity - ) - + let config = ConfigProtocolMock() + let user = UserProfile( avatarUrl: "", name: "Steve", @@ -111,34 +101,35 @@ final class ProfileViewModelTests: XCTestCase { isFullProfile: false, email: "" ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getMyProfileOffline(willReturn: user)) - Given(interactor, .getMyProfile(willReturn: user)) - + + connectivity.isInternetAvaliable = true + interactor.getMyProfileOfflineHandler = { user } + interactor.getMyProfileHandler = { user } + + let viewModel = ProfileViewModel( + interactor: interactor, + router: router, + analytics: analytics, + config: config, + connectivity: connectivity + ) + await viewModel.getMyProfile() - - Verify(interactor, 1, .getMyProfile()) - + + XCTAssertEqual(interactor.getMyProfileCallCount, 1) XCTAssertEqual(viewModel.userModel, user) XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) } - + func testGetMyProfileOfflineSuccess() async throws { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let analytics = ProfileAnalyticsMock() let connectivity = ConnectivityProtocolMock() - let viewModel = ProfileViewModel( - interactor: interactor, - router: router, - analytics: analytics, - config: ConfigMock(), - connectivity: connectivity - ) - + let config = ConfigProtocolMock() + let user = UserProfile( avatarUrl: "", name: "Steve", @@ -150,33 +141,34 @@ final class ProfileViewModelTests: XCTestCase { isFullProfile: false, email: "" ) - - Given(connectivity, .isInternetAvaliable(getter: false)) - Given(interactor, .getMyProfileOffline(willReturn: user)) - + + connectivity.isInternetAvaliable = false + interactor.getMyProfileOfflineHandler = { user } + + let viewModel = ProfileViewModel( + interactor: interactor, + router: router, + analytics: analytics, + config: config, + connectivity: connectivity + ) + await viewModel.getMyProfile() - - Verify(interactor, 1, .getMyProfileOffline()) - + + XCTAssertEqual(interactor.getMyProfileOfflineCallCount, 1) XCTAssertEqual(viewModel.userModel, user) XCTAssertFalse(viewModel.isShowProgress) XCTAssertFalse(viewModel.showError) XCTAssertNil(viewModel.errorMessage) } - + func testGetMyProfileNoInternetError() async throws { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let analytics = ProfileAnalyticsMock() let connectivity = ConnectivityProtocolMock() - let viewModel = ProfileViewModel( - interactor: interactor, - router: router, - analytics: analytics, - config: ConfigMock(), - connectivity: connectivity - ) - + let config = ConfigProtocolMock() + let user = UserProfile( avatarUrl: "", name: "Steve", @@ -188,42 +180,50 @@ final class ProfileViewModelTests: XCTestCase { isFullProfile: false, email: "" ) - + let noInternetError = AFError.sessionInvalidated(error: URLError(.notConnectedToInternet)) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getMyProfileOffline(willReturn: user)) - Given(interactor, .getMyProfile(willThrow: noInternetError)) - + + connectivity.isInternetAvaliable = true + interactor.getMyProfileOfflineHandler = { user } + interactor.getMyProfileHandler = { throw noInternetError } + + let viewModel = ProfileViewModel( + interactor: interactor, + router: router, + analytics: analytics, + config: config, + connectivity: connectivity + ) + await viewModel.getMyProfile() - - Verify(interactor, 1, .getMyProfile()) - + + XCTAssertEqual(interactor.getMyProfileCallCount, 1) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.slowOrNoInternetConnection) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) } - + func testGetMyProfileUnknownError() async throws { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let analytics = ProfileAnalyticsMock() let connectivity = ConnectivityProtocolMock() + let config = ConfigProtocolMock() + + connectivity.isInternetAvaliable = true + interactor.getMyProfileHandler = { throw NSError(domain: "error", code: -1, userInfo: nil) } + let viewModel = ProfileViewModel( interactor: interactor, router: router, analytics: analytics, - config: ConfigMock(), + config: config, connectivity: connectivity ) - - Given(connectivity, .isInternetAvaliable(getter: true)) - Given(interactor, .getMyProfile(willThrow: NSError(domain: "error", code: -1, userInfo: nil))) - + await viewModel.getMyProfile() - - Verify(interactor, 1, .getMyProfile()) - + + XCTAssertEqual(interactor.getMyProfileCallCount, 1) XCTAssertEqual(viewModel.errorMessage, CoreLocalization.Error.unknownError) XCTAssertFalse(viewModel.isShowProgress) XCTAssertTrue(viewModel.showError) diff --git a/Profile/ProfileTests/Presentation/Settings/SettingsViewModelTests.swift b/Profile/ProfileTests/Presentation/Settings/SettingsViewModelTests.swift index 3455d8814..47e1880f9 100644 --- a/Profile/ProfileTests/Presentation/Settings/SettingsViewModelTests.swift +++ b/Profile/ProfileTests/Presentation/Settings/SettingsViewModelTests.swift @@ -2,10 +2,9 @@ // SettingsViewModelTests.swift // ProfileTests // -// Created by  Stepanok Ivan on 10.04.2024. +// Created by Stepanok Ivan on 10.04.2024. // -import SwiftyMocky import XCTest @testable import Core @testable import Profile @@ -21,221 +20,228 @@ final class SettingsViewModelTests: XCTestCase { let analytics = ProfileAnalyticsMock() let coreAnalytics = CoreAnalyticsMock() let storage = CoreStorageMock() - - Given(storage, .updateAppRequired(getter: false)) - Given( - interactor, - .getSettings( - willReturn: UserSettings( - wifiOnly: true, - streamingQuality: .auto, - downloadQuality: .auto, - playbackSpeed: 1.0 - ) + let downloadManager = DownloadManagerProtocolMock() + let corePersistence = CorePersistenceProtocolMock() + let connectivity = ConnectivityProtocolMock() + let config = ConfigProtocolMock() + + storage.updateAppRequired = false + interactor.getSettingsHandler = { + UserSettings( + wifiOnly: true, + streamingQuality: .auto, + downloadQuality: .auto, + playbackSpeed: 1.0 ) - ) - - + } + router.showStartupScreenHandler = { } + interactor.logOutHandler = { } + let viewModel = SettingsViewModel( interactor: interactor, - downloadManager: DownloadManagerMock(), + downloadManager: downloadManager, router: router, analytics: analytics, coreAnalytics: coreAnalytics, - config: ConfigMock(), - corePersistence: CorePersistenceMock(), - connectivity: Connectivity(config: ConfigMock()), + config: config, + corePersistence: corePersistence, + connectivity: connectivity, coreStorage: storage ) - + await viewModel.logOut() - - Verify(router, .showStartupScreen()) + + XCTAssertEqual(router.showStartupScreenCallCount, 1) XCTAssertFalse(viewModel.showError) } - + func testTrackProfileVideoSettingsClicked() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let analytics = ProfileAnalyticsMock() let coreAnalytics = CoreAnalyticsMock() let storage = CoreStorageMock() + let downloadManager = DownloadManagerProtocolMock() + let corePersistence = CorePersistenceProtocolMock() + let connectivity = ConnectivityProtocolMock() + let config = ConfigProtocolMock() - Given(storage, .updateAppRequired(getter: false)) - Given( - interactor, - .getSettings( - willReturn: UserSettings( - wifiOnly: true, - streamingQuality: .auto, - downloadQuality: .auto, - playbackSpeed: 1.0 - ) + storage.updateAppRequired = false + interactor.getSettingsHandler = { + UserSettings( + wifiOnly: true, + streamingQuality: .auto, + downloadQuality: .auto, + playbackSpeed: 1.0 ) - ) - + } + let viewModel = SettingsViewModel( interactor: interactor, - downloadManager: DownloadManagerMock(), + downloadManager: downloadManager, router: router, analytics: analytics, coreAnalytics: coreAnalytics, - config: ConfigMock(), - corePersistence: CorePersistenceMock(), - connectivity: Connectivity(config: ConfigMock()), + config: config, + corePersistence: corePersistence, + connectivity: connectivity, coreStorage: storage ) - + viewModel.trackProfileVideoSettingsClicked() - - Verify(analytics, 1, .profileVideoSettingsClicked()) + + XCTAssertEqual(analytics.profileVideoSettingsClickedCallCount, 1) } - + func testTrackEmailSupportClicked() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let analytics = ProfileAnalyticsMock() let coreAnalytics = CoreAnalyticsMock() let storage = CoreStorageMock() + let downloadManager = DownloadManagerProtocolMock() + let corePersistence = CorePersistenceProtocolMock() + let connectivity = ConnectivityProtocolMock() + let config = ConfigProtocolMock() - Given(storage, .updateAppRequired(getter: false)) - Given( - interactor, - .getSettings( - willReturn: UserSettings( - wifiOnly: true, - streamingQuality: .auto, - downloadQuality: .auto, - playbackSpeed: 1.0 - ) + storage.updateAppRequired = false + interactor.getSettingsHandler = { + UserSettings( + wifiOnly: true, + streamingQuality: .auto, + downloadQuality: .auto, + playbackSpeed: 1.0 ) - ) - + } + let viewModel = SettingsViewModel( interactor: interactor, - downloadManager: DownloadManagerMock(), + downloadManager: downloadManager, router: router, analytics: analytics, coreAnalytics: coreAnalytics, - config: ConfigMock(), - corePersistence: CorePersistenceMock(), - connectivity: Connectivity(config: ConfigMock()), + config: config, + corePersistence: corePersistence, + connectivity: connectivity, coreStorage: storage ) - + viewModel.trackEmailSupportClicked() - - Verify(analytics, 1, .emailSupportClicked()) + + XCTAssertEqual(analytics.emailSupportClickedCallCount, 1) } - + func testTrackCookiePolicyClicked() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let analytics = ProfileAnalyticsMock() let coreAnalytics = CoreAnalyticsMock() let storage = CoreStorageMock() + let downloadManager = DownloadManagerProtocolMock() + let corePersistence = CorePersistenceProtocolMock() + let connectivity = ConnectivityProtocolMock() + let config = ConfigProtocolMock() - Given(storage, .updateAppRequired(getter: false)) - Given( - interactor, - .getSettings( - willReturn: UserSettings( - wifiOnly: true, - streamingQuality: .auto, - downloadQuality: .auto, - playbackSpeed: 1.0 - ) + storage.updateAppRequired = false + interactor.getSettingsHandler = { + UserSettings( + wifiOnly: true, + streamingQuality: .auto, + downloadQuality: .auto, + playbackSpeed: 1.0 ) - ) - + } + let viewModel = SettingsViewModel( interactor: interactor, - downloadManager: DownloadManagerMock(), + downloadManager: downloadManager, router: router, analytics: analytics, coreAnalytics: coreAnalytics, - config: ConfigMock(), - corePersistence: CorePersistenceMock(), - connectivity: Connectivity(config: ConfigMock()), + config: config, + corePersistence: corePersistence, + connectivity: connectivity, coreStorage: storage ) - + viewModel.trackCookiePolicyClicked() - - Verify(analytics, 1, .cookiePolicyClicked()) + + XCTAssertEqual(analytics.cookiePolicyClickedCallCount, 1) } - + func testTrackPrivacyPolicyClicked() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let analytics = ProfileAnalyticsMock() let coreAnalytics = CoreAnalyticsMock() let storage = CoreStorageMock() + let downloadManager = DownloadManagerProtocolMock() + let corePersistence = CorePersistenceProtocolMock() + let connectivity = ConnectivityProtocolMock() + let config = ConfigProtocolMock() - Given(storage, .updateAppRequired(getter: false)) - Given( - interactor, - .getSettings( - willReturn: UserSettings( - wifiOnly: true, - streamingQuality: .auto, - downloadQuality: .auto, - playbackSpeed: 1.0 - ) + storage.updateAppRequired = false + interactor.getSettingsHandler = { + UserSettings( + wifiOnly: true, + streamingQuality: .auto, + downloadQuality: .auto, + playbackSpeed: 1.0 ) - ) - + } + let viewModel = SettingsViewModel( interactor: interactor, - downloadManager: DownloadManagerMock(), + downloadManager: downloadManager, router: router, analytics: analytics, coreAnalytics: coreAnalytics, - config: ConfigMock(), - corePersistence: CorePersistenceMock(), - connectivity: Connectivity(config: ConfigMock()), + config: config, + corePersistence: corePersistence, + connectivity: connectivity, coreStorage: storage ) - + viewModel.trackPrivacyPolicyClicked() - - Verify(analytics, 1, .privacyPolicyClicked()) + + XCTAssertEqual(analytics.privacyPolicyClickedCallCount, 1) } - + func testTrackProfileEditClicked() { let interactor = ProfileInteractorProtocolMock() let router = ProfileRouterMock() let analytics = ProfileAnalyticsMock() let coreAnalytics = CoreAnalyticsMock() let storage = CoreStorageMock() + let downloadManager = DownloadManagerProtocolMock() + let corePersistence = CorePersistenceProtocolMock() + let connectivity = ConnectivityProtocolMock() + let config = ConfigProtocolMock() - Given(storage, .updateAppRequired(getter: false)) - Given( - interactor, - .getSettings( - willReturn: UserSettings( - wifiOnly: true, - streamingQuality: .auto, - downloadQuality: .auto, - playbackSpeed: 1.0 - ) + storage.updateAppRequired = false + interactor.getSettingsHandler = { + UserSettings( + wifiOnly: true, + streamingQuality: .auto, + downloadQuality: .auto, + playbackSpeed: 1.0 ) - ) - + } + let viewModel = SettingsViewModel( interactor: interactor, - downloadManager: DownloadManagerMock(), + downloadManager: downloadManager, router: router, analytics: analytics, coreAnalytics: coreAnalytics, - config: ConfigMock(), - corePersistence: CorePersistenceMock(), - connectivity: Connectivity(config: ConfigMock()), + config: config, + corePersistence: corePersistence, + connectivity: connectivity, coreStorage: storage ) - + viewModel.trackProfileEditClicked() - - Verify(analytics, 1, .profileEditClicked()) + + XCTAssertEqual(analytics.profileEditClickedCallCount, 1) } } diff --git a/Profile/ProfileTests/ProfileMock.generated.swift b/Profile/ProfileTests/ProfileMock.generated.swift deleted file mode 100644 index 9254c0b96..000000000 --- a/Profile/ProfileTests/ProfileMock.generated.swift +++ /dev/null @@ -1,6960 +0,0 @@ -// Generated using Sourcery 2.1.2 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT - - -// Generated with SwiftyMocky 4.2.0 -// Required Sourcery: 1.8.0 - - -import SwiftyMocky -import XCTest -import Core -import Profile -import Foundation -import SwiftUI -import Combine -import OEXFoundation - - -// MARK: - AuthInteractorProtocol - -open class AuthInteractorProtocolMock: AuthInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - @discardableResult - open func login(username: String, password: String) throws -> User { - addInvocation(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) - let perform = methodPerformValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))) as? (String, String) -> Void - perform?(`username`, `password`) - var __value: User - do { - __value = try methodReturnValue(.m_login__username_usernamepassword_password(Parameter.value(`username`), Parameter.value(`password`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(username: String, password: String). Use given") - Failure("Stub return value not specified for login(username: String, password: String). Use given") - } catch { - throw error - } - return __value - } - - @discardableResult - open func login(externalToken: String, backend: String) throws -> User { - addInvocation(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) - let perform = methodPerformValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))) as? (String, String) -> Void - perform?(`externalToken`, `backend`) - var __value: User - do { - __value = try methodReturnValue(.m_login__externalToken_externalTokenbackend_backend(Parameter.value(`externalToken`), Parameter.value(`backend`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - Failure("Stub return value not specified for login(externalToken: String, backend: String). Use given") - } catch { - throw error - } - return __value - } - - open func login(ssoToken: String) throws -> User { - addInvocation(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) - let perform = methodPerformValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))) as? (String) -> Void - perform?(`ssoToken`) - var __value: User - do { - __value = try methodReturnValue(.m_login__ssoToken_ssoToken(Parameter.value(`ssoToken`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for login(ssoToken: String). Use given") - Failure("Stub return value not specified for login(ssoToken: String). Use given") - } catch { - throw error - } - return __value - } - - open func resetPassword(email: String) throws -> ResetPassword { - addInvocation(.m_resetPassword__email_email(Parameter.value(`email`))) - let perform = methodPerformValue(.m_resetPassword__email_email(Parameter.value(`email`))) as? (String) -> Void - perform?(`email`) - var __value: ResetPassword - do { - __value = try methodReturnValue(.m_resetPassword__email_email(Parameter.value(`email`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for resetPassword(email: String). Use given") - Failure("Stub return value not specified for resetPassword(email: String). Use given") - } catch { - throw error - } - return __value - } - - open func getCookies(force: Bool) throws { - addInvocation(.m_getCookies__force_force(Parameter.value(`force`))) - let perform = methodPerformValue(.m_getCookies__force_force(Parameter.value(`force`))) as? (Bool) -> Void - perform?(`force`) - do { - _ = try methodReturnValue(.m_getCookies__force_force(Parameter.value(`force`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getRegistrationFields() throws -> [PickerFields] { - addInvocation(.m_getRegistrationFields) - let perform = methodPerformValue(.m_getRegistrationFields) as? () -> Void - perform?() - var __value: [PickerFields] - do { - __value = try methodReturnValue(.m_getRegistrationFields).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getRegistrationFields(). Use given") - Failure("Stub return value not specified for getRegistrationFields(). Use given") - } catch { - throw error - } - return __value - } - - open func registerUser(fields: [String: String], isSocial: Bool) throws -> User { - addInvocation(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) - let perform = methodPerformValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))) as? ([String: String], Bool) -> Void - perform?(`fields`, `isSocial`) - var __value: User - do { - __value = try methodReturnValue(.m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>.value(`fields`), Parameter.value(`isSocial`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - Failure("Stub return value not specified for registerUser(fields: [String: String], isSocial: Bool). Use given") - } catch { - throw error - } - return __value - } - - open func validateRegistrationFields(fields: [String: String]) throws -> [String: String] { - addInvocation(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) - let perform = methodPerformValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))) as? ([String: String]) -> Void - perform?(`fields`) - var __value: [String: String] - do { - __value = try methodReturnValue(.m_validateRegistrationFields__fields_fields(Parameter<[String: String]>.value(`fields`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - Failure("Stub return value not specified for validateRegistrationFields(fields: [String: String]). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_login__username_usernamepassword_password(Parameter, Parameter) - case m_login__externalToken_externalTokenbackend_backend(Parameter, Parameter) - case m_login__ssoToken_ssoToken(Parameter) - case m_resetPassword__email_email(Parameter) - case m_getCookies__force_force(Parameter) - case m_getRegistrationFields - case m_registerUser__fields_fieldsisSocial_isSocial(Parameter<[String: String]>, Parameter) - case m_validateRegistrationFields__fields_fields(Parameter<[String: String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_login__username_usernamepassword_password(let lhsUsername, let lhsPassword), .m_login__username_usernamepassword_password(let rhsUsername, let rhsPassword)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsername, rhs: rhsUsername, with: matcher), lhsUsername, rhsUsername, "username")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPassword, rhs: rhsPassword, with: matcher), lhsPassword, rhsPassword, "password")) - return Matcher.ComparisonResult(results) - - case (.m_login__externalToken_externalTokenbackend_backend(let lhsExternaltoken, let lhsBackend), .m_login__externalToken_externalTokenbackend_backend(let rhsExternaltoken, let rhsBackend)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsExternaltoken, rhs: rhsExternaltoken, with: matcher), lhsExternaltoken, rhsExternaltoken, "externalToken")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBackend, rhs: rhsBackend, with: matcher), lhsBackend, rhsBackend, "backend")) - return Matcher.ComparisonResult(results) - - case (.m_login__ssoToken_ssoToken(let lhsSsotoken), .m_login__ssoToken_ssoToken(let rhsSsotoken)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSsotoken, rhs: rhsSsotoken, with: matcher), lhsSsotoken, rhsSsotoken, "ssoToken")) - return Matcher.ComparisonResult(results) - - case (.m_resetPassword__email_email(let lhsEmail), .m_resetPassword__email_email(let rhsEmail)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEmail, rhs: rhsEmail, with: matcher), lhsEmail, rhsEmail, "email")) - return Matcher.ComparisonResult(results) - - case (.m_getCookies__force_force(let lhsForce), .m_getCookies__force_force(let rhsForce)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsForce, rhs: rhsForce, with: matcher), lhsForce, rhsForce, "force")) - return Matcher.ComparisonResult(results) - - case (.m_getRegistrationFields, .m_getRegistrationFields): return .match - - case (.m_registerUser__fields_fieldsisSocial_isSocial(let lhsFields, let lhsIssocial), .m_registerUser__fields_fieldsisSocial_isSocial(let rhsFields, let rhsIssocial)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIssocial, rhs: rhsIssocial, with: matcher), lhsIssocial, rhsIssocial, "isSocial")) - return Matcher.ComparisonResult(results) - - case (.m_validateRegistrationFields__fields_fields(let lhsFields), .m_validateRegistrationFields__fields_fields(let rhsFields)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFields, rhs: rhsFields, with: matcher), lhsFields, rhsFields, "fields")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_login__username_usernamepassword_password(p0, p1): return p0.intValue + p1.intValue - case let .m_login__externalToken_externalTokenbackend_backend(p0, p1): return p0.intValue + p1.intValue - case let .m_login__ssoToken_ssoToken(p0): return p0.intValue - case let .m_resetPassword__email_email(p0): return p0.intValue - case let .m_getCookies__force_force(p0): return p0.intValue - case .m_getRegistrationFields: return 0 - case let .m_registerUser__fields_fieldsisSocial_isSocial(p0, p1): return p0.intValue + p1.intValue - case let .m_validateRegistrationFields__fields_fields(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_login__username_usernamepassword_password: return ".login(username:password:)" - case .m_login__externalToken_externalTokenbackend_backend: return ".login(externalToken:backend:)" - case .m_login__ssoToken_ssoToken: return ".login(ssoToken:)" - case .m_resetPassword__email_email: return ".resetPassword(email:)" - case .m_getCookies__force_force: return ".getCookies(force:)" - case .m_getRegistrationFields: return ".getRegistrationFields()" - case .m_registerUser__fields_fieldsisSocial_isSocial: return ".registerUser(fields:isSocial:)" - case .m_validateRegistrationFields__fields_fields: return ".validateRegistrationFields(fields:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - @discardableResult - public static func login(username: Parameter, password: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func login(ssoToken: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func resetPassword(email: Parameter, willReturn: ResetPassword...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getRegistrationFields(willReturn: [PickerFields]...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willReturn: User...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willReturn: [String: String]...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(username: Parameter, password: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__username_usernamepassword_password(`username`, `password`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func login(ssoToken: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func login(ssoToken: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_login__ssoToken_ssoToken(`ssoToken`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func resetPassword(email: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resetPassword(email: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resetPassword__email_email(`email`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (ResetPassword).self) - willProduce(stubber) - return given - } - public static func getCookies(force: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCookies(force: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCookies__force_force(`force`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func getRegistrationFields(willThrow: Error...) -> MethodStub { - return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getRegistrationFields(willProduce: (StubberThrows<[PickerFields]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getRegistrationFields, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([PickerFields]).self) - willProduce(stubber) - return given - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (User).self) - willProduce(stubber) - return given - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, willProduce: (StubberThrows<[String: String]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_validateRegistrationFields__fields_fields(`fields`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([String: String]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - @discardableResult - public static func login(username: Parameter, password: Parameter) -> Verify { return Verify(method: .m_login__username_usernamepassword_password(`username`, `password`))} - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter) -> Verify { return Verify(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`))} - public static func login(ssoToken: Parameter) -> Verify { return Verify(method: .m_login__ssoToken_ssoToken(`ssoToken`))} - public static func resetPassword(email: Parameter) -> Verify { return Verify(method: .m_resetPassword__email_email(`email`))} - public static func getCookies(force: Parameter) -> Verify { return Verify(method: .m_getCookies__force_force(`force`))} - public static func getRegistrationFields() -> Verify { return Verify(method: .m_getRegistrationFields)} - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter) -> Verify { return Verify(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`))} - public static func validateRegistrationFields(fields: Parameter<[String: String]>) -> Verify { return Verify(method: .m_validateRegistrationFields__fields_fields(`fields`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - @discardableResult - public static func login(username: Parameter, password: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__username_usernamepassword_password(`username`, `password`), performs: perform) - } - @discardableResult - public static func login(externalToken: Parameter, backend: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_login__externalToken_externalTokenbackend_backend(`externalToken`, `backend`), performs: perform) - } - public static func login(ssoToken: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_login__ssoToken_ssoToken(`ssoToken`), performs: perform) - } - public static func resetPassword(email: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_resetPassword__email_email(`email`), performs: perform) - } - public static func getCookies(force: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_getCookies__force_force(`force`), performs: perform) - } - public static func getRegistrationFields(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getRegistrationFields, performs: perform) - } - public static func registerUser(fields: Parameter<[String: String]>, isSocial: Parameter, perform: @escaping ([String: String], Bool) -> Void) -> Perform { - return Perform(method: .m_registerUser__fields_fieldsisSocial_isSocial(`fields`, `isSocial`), performs: perform) - } - public static func validateRegistrationFields(fields: Parameter<[String: String]>, perform: @escaping ([String: String]) -> Void) -> Perform { - return Perform(method: .m_validateRegistrationFields__fields_fields(`fields`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - BaseRouter -@MainActor -open class BaseRouterMock: BaseRouter, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func backToRoot(animated: Bool) { - addInvocation(.m_backToRoot__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_backToRoot__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func back(animated: Bool) { - addInvocation(.m_back__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_back__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func backWithFade() { - addInvocation(.m_backWithFade) - let perform = methodPerformValue(.m_backWithFade) as? () -> Void - perform?() - } - - open func dismiss(animated: Bool) { - addInvocation(.m_dismiss__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_dismiss__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func removeLastView(controllers: Int) { - addInvocation(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) - let perform = methodPerformValue(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) as? (Int) -> Void - perform?(`controllers`) - } - - open func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { - addInvocation(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) - let perform = methodPerformValue(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) as? (LogistrationSourceScreen, PostLoginData?) -> Void - perform?(`sourceScreen`, `postLoginData`) - } - - open func showStartupScreen() { - addInvocation(.m_showStartupScreen) - let perform = methodPerformValue(.m_showStartupScreen) as? () -> Void - perform?() - } - - open func showLoginScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showForgotPasswordScreen() { - addInvocation(.m_showForgotPasswordScreen) - let perform = methodPerformValue(.m_showForgotPasswordScreen) as? () -> Void - perform?() - } - - open func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) as? (String?, LogistrationSourceScreen) -> Void - perform?(`searchQuery`, `sourceScreen`) - } - - open func showWebBrowser(title: String, url: URL) { - addInvocation(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) - let perform = methodPerformValue(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) as? (String, URL) -> Void - perform?(`title`, `url`) - } - - open func showSSOWebBrowser(title: String) { - addInvocation(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) - let perform = methodPerformValue(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) as? (String) -> Void - perform?(`title`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) as? (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void - perform?(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) as? (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void - perform?(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { - addInvocation(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) as? (UIModalTransitionStyle, any View, (() -> Void)?) -> Void - perform?(`transitionStyle`, `view`, `completion`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { - addInvocation(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) as? (UIModalTransitionStyle, Bool, () -> any View) -> Void - perform?(`transitionStyle`, `animated`, `content`) - } - - - fileprivate enum MethodType { - case m_backToRoot__animated_animated(Parameter) - case m_back__animated_animated(Parameter) - case m_backWithFade - case m_dismiss__animated_animated(Parameter) - case m_removeLastView__controllers_controllers(Parameter) - case m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter, Parameter) - case m_showStartupScreen - case m_showLoginScreen__sourceScreen_sourceScreen(Parameter) - case m_showRegisterScreen__sourceScreen_sourceScreen(Parameter) - case m_showForgotPasswordScreen - case m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter, Parameter) - case m_showWebBrowser__title_titleurl_url(Parameter, Parameter) - case m_showSSOWebBrowser__title_title(Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter<() -> Void>) - case m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter, Parameter, Parameter<(() -> Void)?>) - case m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter, Parameter, Parameter<() -> any View>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_backToRoot__animated_animated(let lhsAnimated), .m_backToRoot__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_back__animated_animated(let lhsAnimated), .m_back__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_backWithFade, .m_backWithFade): return .match - - case (.m_dismiss__animated_animated(let lhsAnimated), .m_dismiss__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_removeLastView__controllers_controllers(let lhsControllers), .m_removeLastView__controllers_controllers(let rhsControllers)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsControllers, rhs: rhsControllers, with: matcher), lhsControllers, rhsControllers, "controllers")) - return Matcher.ComparisonResult(results) - - case (.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let lhsSourcescreen, let lhsPostlogindata), .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let rhsSourcescreen, let rhsPostlogindata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPostlogindata, rhs: rhsPostlogindata, with: matcher), lhsPostlogindata, rhsPostlogindata, "postLoginData")) - return Matcher.ComparisonResult(results) - - case (.m_showStartupScreen, .m_showStartupScreen): return .match - - case (.m_showLoginScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showLoginScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showRegisterScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showRegisterScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showForgotPasswordScreen, .m_showForgotPasswordScreen): return .match - - case (.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let lhsSearchquery, let lhsSourcescreen), .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let rhsSearchquery, let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchquery, rhs: rhsSearchquery, with: matcher), lhsSearchquery, rhsSearchquery, "searchQuery")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showWebBrowser__title_titleurl_url(let lhsTitle, let lhsUrl), .m_showWebBrowser__title_titleurl_url(let rhsTitle, let rhsUrl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - return Matcher.ComparisonResult(results) - - case (.m_showSSOWebBrowser__title_title(let lhsTitle), .m_showSSOWebBrowser__title_title(let rhsTitle)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let lhsAlerttitle, let lhsAlertmessage, let lhsPositiveaction, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsType), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let rhsAlerttitle, let rhsAlertmessage, let rhsPositiveaction, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPositiveaction, rhs: rhsPositiveaction, with: matcher), lhsPositiveaction, rhsPositiveaction, "positiveAction")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let lhsAlerttitle, let lhsAlertmessage, let lhsNextsectionname, let lhsAction, let lhsImage, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsNextsectiontapped), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let rhsAlerttitle, let rhsAlertmessage, let rhsNextsectionname, let rhsAction, let rhsImage, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsNextsectiontapped)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectionname, rhs: rhsNextsectionname, with: matcher), lhsNextsectionname, rhsNextsectionname, "nextSectionName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsImage, rhs: rhsImage, with: matcher), lhsImage, rhsImage, "image")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectiontapped, rhs: rhsNextsectiontapped, with: matcher), lhsNextsectiontapped, rhsNextsectiontapped, "nextSectionTapped")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let lhsTransitionstyle, let lhsView, let lhsCompletion), .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let rhsTransitionstyle, let rhsView, let rhsCompletion)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsView, rhs: rhsView, with: matcher), lhsView, rhsView, "view")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCompletion, rhs: rhsCompletion, with: matcher), lhsCompletion, rhsCompletion, "completion")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let lhsTransitionstyle, let lhsAnimated, let lhsContent), .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let rhsTransitionstyle, let rhsAnimated, let rhsContent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsContent, rhs: rhsContent, with: matcher), lhsContent, rhsContent, "content")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_backToRoot__animated_animated(p0): return p0.intValue - case let .m_back__animated_animated(p0): return p0.intValue - case .m_backWithFade: return 0 - case let .m_dismiss__animated_animated(p0): return p0.intValue - case let .m_removeLastView__controllers_controllers(p0): return p0.intValue - case let .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(p0, p1): return p0.intValue + p1.intValue - case .m_showStartupScreen: return 0 - case let .m_showLoginScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case let .m_showRegisterScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case .m_showForgotPasswordScreen: return 0 - case let .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(p0, p1): return p0.intValue + p1.intValue - case let .m_showWebBrowser__title_titleurl_url(p0, p1): return p0.intValue + p1.intValue - case let .m_showSSOWebBrowser__title_title(p0): return p0.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(p0, p1, p2, p3, p4, p5, p6, p7): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue + p7.intValue - case let .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_backToRoot__animated_animated: return ".backToRoot(animated:)" - case .m_back__animated_animated: return ".back(animated:)" - case .m_backWithFade: return ".backWithFade()" - case .m_dismiss__animated_animated: return ".dismiss(animated:)" - case .m_removeLastView__controllers_controllers: return ".removeLastView(controllers:)" - case .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData: return ".showMainOrWhatsNewScreen(sourceScreen:postLoginData:)" - case .m_showStartupScreen: return ".showStartupScreen()" - case .m_showLoginScreen__sourceScreen_sourceScreen: return ".showLoginScreen(sourceScreen:)" - case .m_showRegisterScreen__sourceScreen_sourceScreen: return ".showRegisterScreen(sourceScreen:)" - case .m_showForgotPasswordScreen: return ".showForgotPasswordScreen()" - case .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen: return ".showDiscoveryScreen(searchQuery:sourceScreen:)" - case .m_showWebBrowser__title_titleurl_url: return ".showWebBrowser(title:url:)" - case .m_showSSOWebBrowser__title_title: return ".showSSOWebBrowser(title:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type: return ".presentAlert(alertTitle:alertMessage:positiveAction:onCloseTapped:firstButtonTapped:type:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped: return ".presentAlert(alertTitle:alertMessage:nextSectionName:action:image:onCloseTapped:firstButtonTapped:nextSectionTapped:)" - case .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion: return ".presentView(transitionStyle:view:completion:)" - case .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content: return ".presentView(transitionStyle:animated:content:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func backToRoot(animated: Parameter) -> Verify { return Verify(method: .m_backToRoot__animated_animated(`animated`))} - public static func back(animated: Parameter) -> Verify { return Verify(method: .m_back__animated_animated(`animated`))} - public static func backWithFade() -> Verify { return Verify(method: .m_backWithFade)} - public static func dismiss(animated: Parameter) -> Verify { return Verify(method: .m_dismiss__animated_animated(`animated`))} - public static func removeLastView(controllers: Parameter) -> Verify { return Verify(method: .m_removeLastView__controllers_controllers(`controllers`))} - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter) -> Verify { return Verify(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`))} - public static func showStartupScreen() -> Verify { return Verify(method: .m_showStartupScreen)} - public static func showLoginScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showRegisterScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showForgotPasswordScreen() -> Verify { return Verify(method: .m_showForgotPasswordScreen)} - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter) -> Verify { return Verify(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`))} - public static func showWebBrowser(title: Parameter, url: Parameter) -> Verify { return Verify(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`))} - public static func showSSOWebBrowser(title: Parameter) -> Verify { return Verify(method: .m_showSSOWebBrowser__title_title(`title`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`))} - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`))} - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func backToRoot(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_backToRoot__animated_animated(`animated`), performs: perform) - } - public static func back(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_back__animated_animated(`animated`), performs: perform) - } - public static func backWithFade(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_backWithFade, performs: perform) - } - public static func dismiss(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_dismiss__animated_animated(`animated`), performs: perform) - } - public static func removeLastView(controllers: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_removeLastView__controllers_controllers(`controllers`), performs: perform) - } - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter, perform: @escaping (LogistrationSourceScreen, PostLoginData?) -> Void) -> Perform { - return Perform(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`), performs: perform) - } - public static func showStartupScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showStartupScreen, performs: perform) - } - public static func showLoginScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showRegisterScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showForgotPasswordScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showForgotPasswordScreen, performs: perform) - } - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter, perform: @escaping (String?, LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`), performs: perform) - } - public static func showWebBrowser(title: Parameter, url: Parameter, perform: @escaping (String, URL) -> Void) -> Perform { - return Perform(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`), performs: perform) - } - public static func showSSOWebBrowser(title: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showSSOWebBrowser__title_title(`title`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter, perform: @escaping (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>, perform: @escaping (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>, perform: @escaping (UIModalTransitionStyle, any View, (() -> Void)?) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>, perform: @escaping (UIModalTransitionStyle, Bool, () -> any View) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CalendarManagerProtocol -@MainActor -open class CalendarManagerProtocolMock: CalendarManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func createCalendarIfNeeded() { - addInvocation(.m_createCalendarIfNeeded) - let perform = methodPerformValue(.m_createCalendarIfNeeded) as? () -> Void - perform?() - } - - open func filterCoursesBySelected(fetchedCourses: [CourseForSync]) -> [CourseForSync] { - addInvocation(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) - let perform = methodPerformValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))) as? ([CourseForSync]) -> Void - perform?(`fetchedCourses`) - var __value: [CourseForSync] - do { - __value = try methodReturnValue(.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>.value(`fetchedCourses`))).casted() - } catch { - onFatalFailure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - Failure("Stub return value not specified for filterCoursesBySelected(fetchedCourses: [CourseForSync]). Use given") - } - return __value - } - - open func removeOldCalendar() { - addInvocation(.m_removeOldCalendar) - let perform = methodPerformValue(.m_removeOldCalendar) as? () -> Void - perform?() - } - - open func removeOutdatedEvents(courseID: String) { - addInvocation(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_removeOutdatedEvents__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - } - - open func syncCourse(courseID: String, courseName: String, dates: CourseDates) { - addInvocation(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) - let perform = methodPerformValue(.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter.value(`courseID`), Parameter.value(`courseName`), Parameter.value(`dates`))) as? (String, String, CourseDates) -> Void - perform?(`courseID`, `courseName`, `dates`) - } - - open func requestAccess() -> Bool { - addInvocation(.m_requestAccess) - let perform = methodPerformValue(.m_requestAccess) as? () -> Void - perform?() - var __value: Bool - do { - __value = try methodReturnValue(.m_requestAccess).casted() - } catch { - onFatalFailure("Stub return value not specified for requestAccess(). Use given") - Failure("Stub return value not specified for requestAccess(). Use given") - } - return __value - } - - open func courseStatus(courseID: String) -> SyncStatus { - addInvocation(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: SyncStatus - do { - __value = try methodReturnValue(.m_courseStatus__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - onFatalFailure("Stub return value not specified for courseStatus(courseID: String). Use given") - Failure("Stub return value not specified for courseStatus(courseID: String). Use given") - } - return __value - } - - open func clearAllData(removeCalendar: Bool) { - addInvocation(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) - let perform = methodPerformValue(.m_clearAllData__removeCalendar_removeCalendar(Parameter.value(`removeCalendar`))) as? (Bool) -> Void - perform?(`removeCalendar`) - } - - open func isDatesChanged(courseID: String, checksum: String) -> Bool { - addInvocation(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) - let perform = methodPerformValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))) as? (String, String) -> Void - perform?(`courseID`, `checksum`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter.value(`courseID`), Parameter.value(`checksum`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - Failure("Stub return value not specified for isDatesChanged(courseID: String, checksum: String). Use given") - } - return __value - } - - - fileprivate enum MethodType { - case m_createCalendarIfNeeded - case m_filterCoursesBySelected__fetchedCourses_fetchedCourses(Parameter<[CourseForSync]>) - case m_removeOldCalendar - case m_removeOutdatedEvents__courseID_courseID(Parameter) - case m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(Parameter, Parameter, Parameter) - case m_requestAccess - case m_courseStatus__courseID_courseID(Parameter) - case m_clearAllData__removeCalendar_removeCalendar(Parameter) - case m_isDatesChanged__courseID_courseIDchecksum_checksum(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_createCalendarIfNeeded, .m_createCalendarIfNeeded): return .match - - case (.m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let lhsFetchedcourses), .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(let rhsFetchedcourses)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFetchedcourses, rhs: rhsFetchedcourses, with: matcher), lhsFetchedcourses, rhsFetchedcourses, "fetchedCourses")) - return Matcher.ComparisonResult(results) - - case (.m_removeOldCalendar, .m_removeOldCalendar): return .match - - case (.m_removeOutdatedEvents__courseID_courseID(let lhsCourseid), .m_removeOutdatedEvents__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let lhsCourseid, let lhsCoursename, let lhsDates), .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(let rhsCourseid, let rhsCoursename, let rhsDates)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCoursename, rhs: rhsCoursename, with: matcher), lhsCoursename, rhsCoursename, "courseName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDates, rhs: rhsDates, with: matcher), lhsDates, rhsDates, "dates")) - return Matcher.ComparisonResult(results) - - case (.m_requestAccess, .m_requestAccess): return .match - - case (.m_courseStatus__courseID_courseID(let lhsCourseid), .m_courseStatus__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_clearAllData__removeCalendar_removeCalendar(let lhsRemovecalendar), .m_clearAllData__removeCalendar_removeCalendar(let rhsRemovecalendar)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRemovecalendar, rhs: rhsRemovecalendar, with: matcher), lhsRemovecalendar, rhsRemovecalendar, "removeCalendar")) - return Matcher.ComparisonResult(results) - - case (.m_isDatesChanged__courseID_courseIDchecksum_checksum(let lhsCourseid, let lhsChecksum), .m_isDatesChanged__courseID_courseIDchecksum_checksum(let rhsCourseid, let rhsChecksum)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsChecksum, rhs: rhsChecksum, with: matcher), lhsChecksum, rhsChecksum, "checksum")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_createCalendarIfNeeded: return 0 - case let .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(p0): return p0.intValue - case .m_removeOldCalendar: return 0 - case let .m_removeOutdatedEvents__courseID_courseID(p0): return p0.intValue - case let .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case .m_requestAccess: return 0 - case let .m_courseStatus__courseID_courseID(p0): return p0.intValue - case let .m_clearAllData__removeCalendar_removeCalendar(p0): return p0.intValue - case let .m_isDatesChanged__courseID_courseIDchecksum_checksum(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_createCalendarIfNeeded: return ".createCalendarIfNeeded()" - case .m_filterCoursesBySelected__fetchedCourses_fetchedCourses: return ".filterCoursesBySelected(fetchedCourses:)" - case .m_removeOldCalendar: return ".removeOldCalendar()" - case .m_removeOutdatedEvents__courseID_courseID: return ".removeOutdatedEvents(courseID:)" - case .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates: return ".syncCourse(courseID:courseName:dates:)" - case .m_requestAccess: return ".requestAccess()" - case .m_courseStatus__courseID_courseID: return ".courseStatus(courseID:)" - case .m_clearAllData__removeCalendar_removeCalendar: return ".clearAllData(removeCalendar:)" - case .m_isDatesChanged__courseID_courseIDchecksum_checksum: return ".isDatesChanged(courseID:checksum:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willReturn: [CourseForSync]...) -> MethodStub { - return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func requestAccess(willReturn: Bool...) -> MethodStub { - return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func courseStatus(courseID: Parameter, willReturn: SyncStatus...) -> MethodStub { - return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, willProduce: (Stubber<[CourseForSync]>) -> Void) -> MethodStub { - let willReturn: [[CourseForSync]] = [] - let given: Given = { return Given(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([CourseForSync]).self) - willProduce(stubber) - return given - } - public static func requestAccess(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_requestAccess, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func courseStatus(courseID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [SyncStatus] = [] - let given: Given = { return Given(method: .m_courseStatus__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (SyncStatus).self) - willProduce(stubber) - return given - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func createCalendarIfNeeded() -> Verify { return Verify(method: .m_createCalendarIfNeeded)} - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>) -> Verify { return Verify(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`))} - public static func removeOldCalendar() -> Verify { return Verify(method: .m_removeOldCalendar)} - public static func removeOutdatedEvents(courseID: Parameter) -> Verify { return Verify(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`))} - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter) -> Verify { return Verify(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`))} - public static func requestAccess() -> Verify { return Verify(method: .m_requestAccess)} - public static func courseStatus(courseID: Parameter) -> Verify { return Verify(method: .m_courseStatus__courseID_courseID(`courseID`))} - public static func clearAllData(removeCalendar: Parameter) -> Verify { return Verify(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`))} - public static func isDatesChanged(courseID: Parameter, checksum: Parameter) -> Verify { return Verify(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func createCalendarIfNeeded(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_createCalendarIfNeeded, performs: perform) - } - public static func filterCoursesBySelected(fetchedCourses: Parameter<[CourseForSync]>, perform: @escaping ([CourseForSync]) -> Void) -> Perform { - return Perform(method: .m_filterCoursesBySelected__fetchedCourses_fetchedCourses(`fetchedCourses`), performs: perform) - } - public static func removeOldCalendar(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeOldCalendar, performs: perform) - } - public static func removeOutdatedEvents(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_removeOutdatedEvents__courseID_courseID(`courseID`), performs: perform) - } - public static func syncCourse(courseID: Parameter, courseName: Parameter, dates: Parameter, perform: @escaping (String, String, CourseDates) -> Void) -> Perform { - return Perform(method: .m_syncCourse__courseID_courseIDcourseName_courseNamedates_dates(`courseID`, `courseName`, `dates`), performs: perform) - } - public static func requestAccess(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_requestAccess, performs: perform) - } - public static func courseStatus(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_courseStatus__courseID_courseID(`courseID`), performs: perform) - } - public static func clearAllData(removeCalendar: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_clearAllData__removeCalendar_removeCalendar(`removeCalendar`), performs: perform) - } - public static func isDatesChanged(courseID: Parameter, checksum: Parameter, perform: @escaping (String, String) -> Void) -> Perform { - return Perform(method: .m_isDatesChanged__courseID_courseIDchecksum_checksum(`courseID`, `checksum`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConfigProtocol - -open class ConfigProtocolMock: ConfigProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var baseURL: URL { - get { invocations.append(.p_baseURL_get); return __p_baseURL ?? givenGetterValue(.p_baseURL_get, "ConfigProtocolMock - stub value for baseURL was not defined") } - } - private var __p_baseURL: (URL)? - - public var baseSSOURL: URL { - get { invocations.append(.p_baseSSOURL_get); return __p_baseSSOURL ?? givenGetterValue(.p_baseSSOURL_get, "ConfigProtocolMock - stub value for baseSSOURL was not defined") } - } - private var __p_baseSSOURL: (URL)? - - public var ssoFinishedURL: URL { - get { invocations.append(.p_ssoFinishedURL_get); return __p_ssoFinishedURL ?? givenGetterValue(.p_ssoFinishedURL_get, "ConfigProtocolMock - stub value for ssoFinishedURL was not defined") } - } - private var __p_ssoFinishedURL: (URL)? - - public var ssoButtonTitle: [String: Any] { - get { invocations.append(.p_ssoButtonTitle_get); return __p_ssoButtonTitle ?? givenGetterValue(.p_ssoButtonTitle_get, "ConfigProtocolMock - stub value for ssoButtonTitle was not defined") } - } - private var __p_ssoButtonTitle: ([String: Any])? - - public var oAuthClientId: String { - get { invocations.append(.p_oAuthClientId_get); return __p_oAuthClientId ?? givenGetterValue(.p_oAuthClientId_get, "ConfigProtocolMock - stub value for oAuthClientId was not defined") } - } - private var __p_oAuthClientId: (String)? - - public var tokenType: TokenType { - get { invocations.append(.p_tokenType_get); return __p_tokenType ?? givenGetterValue(.p_tokenType_get, "ConfigProtocolMock - stub value for tokenType was not defined") } - } - private var __p_tokenType: (TokenType)? - - public var feedbackEmail: String { - get { invocations.append(.p_feedbackEmail_get); return __p_feedbackEmail ?? givenGetterValue(.p_feedbackEmail_get, "ConfigProtocolMock - stub value for feedbackEmail was not defined") } - } - private var __p_feedbackEmail: (String)? - - public var appStoreLink: String { - get { invocations.append(.p_appStoreLink_get); return __p_appStoreLink ?? givenGetterValue(.p_appStoreLink_get, "ConfigProtocolMock - stub value for appStoreLink was not defined") } - } - private var __p_appStoreLink: (String)? - - public var faq: URL? { - get { invocations.append(.p_faq_get); return __p_faq ?? optionalGivenGetterValue(.p_faq_get, "ConfigProtocolMock - stub value for faq was not defined") } - } - private var __p_faq: (URL)? - - public var platformName: String { - get { invocations.append(.p_platformName_get); return __p_platformName ?? givenGetterValue(.p_platformName_get, "ConfigProtocolMock - stub value for platformName was not defined") } - } - private var __p_platformName: (String)? - - public var agreement: AgreementConfig { - get { invocations.append(.p_agreement_get); return __p_agreement ?? givenGetterValue(.p_agreement_get, "ConfigProtocolMock - stub value for agreement was not defined") } - } - private var __p_agreement: (AgreementConfig)? - - public var firebase: FirebaseConfig { - get { invocations.append(.p_firebase_get); return __p_firebase ?? givenGetterValue(.p_firebase_get, "ConfigProtocolMock - stub value for firebase was not defined") } - } - private var __p_firebase: (FirebaseConfig)? - - public var facebook: FacebookConfig { - get { invocations.append(.p_facebook_get); return __p_facebook ?? givenGetterValue(.p_facebook_get, "ConfigProtocolMock - stub value for facebook was not defined") } - } - private var __p_facebook: (FacebookConfig)? - - public var microsoft: MicrosoftConfig { - get { invocations.append(.p_microsoft_get); return __p_microsoft ?? givenGetterValue(.p_microsoft_get, "ConfigProtocolMock - stub value for microsoft was not defined") } - } - private var __p_microsoft: (MicrosoftConfig)? - - public var google: GoogleConfig { - get { invocations.append(.p_google_get); return __p_google ?? givenGetterValue(.p_google_get, "ConfigProtocolMock - stub value for google was not defined") } - } - private var __p_google: (GoogleConfig)? - - public var appleSignIn: AppleSignInConfig { - get { invocations.append(.p_appleSignIn_get); return __p_appleSignIn ?? givenGetterValue(.p_appleSignIn_get, "ConfigProtocolMock - stub value for appleSignIn was not defined") } - } - private var __p_appleSignIn: (AppleSignInConfig)? - - public var features: FeaturesConfig { - get { invocations.append(.p_features_get); return __p_features ?? givenGetterValue(.p_features_get, "ConfigProtocolMock - stub value for features was not defined") } - } - private var __p_features: (FeaturesConfig)? - - public var theme: ThemeConfig { - get { invocations.append(.p_theme_get); return __p_theme ?? givenGetterValue(.p_theme_get, "ConfigProtocolMock - stub value for theme was not defined") } - } - private var __p_theme: (ThemeConfig)? - - public var uiComponents: UIComponentsConfig { - get { invocations.append(.p_uiComponents_get); return __p_uiComponents ?? givenGetterValue(.p_uiComponents_get, "ConfigProtocolMock - stub value for uiComponents was not defined") } - } - private var __p_uiComponents: (UIComponentsConfig)? - - public var discovery: DiscoveryConfig { - get { invocations.append(.p_discovery_get); return __p_discovery ?? givenGetterValue(.p_discovery_get, "ConfigProtocolMock - stub value for discovery was not defined") } - } - private var __p_discovery: (DiscoveryConfig)? - - public var dashboard: DashboardConfig { - get { invocations.append(.p_dashboard_get); return __p_dashboard ?? givenGetterValue(.p_dashboard_get, "ConfigProtocolMock - stub value for dashboard was not defined") } - } - private var __p_dashboard: (DashboardConfig)? - - public var braze: BrazeConfig { - get { invocations.append(.p_braze_get); return __p_braze ?? givenGetterValue(.p_braze_get, "ConfigProtocolMock - stub value for braze was not defined") } - } - private var __p_braze: (BrazeConfig)? - - public var branch: BranchConfig { - get { invocations.append(.p_branch_get); return __p_branch ?? givenGetterValue(.p_branch_get, "ConfigProtocolMock - stub value for branch was not defined") } - } - private var __p_branch: (BranchConfig)? - - public var program: DiscoveryConfig { - get { invocations.append(.p_program_get); return __p_program ?? givenGetterValue(.p_program_get, "ConfigProtocolMock - stub value for program was not defined") } - } - private var __p_program: (DiscoveryConfig)? - - public var experimentalFeatures: ExperimentalFeaturesConfig { - get { invocations.append(.p_experimentalFeatures_get); return __p_experimentalFeatures ?? givenGetterValue(.p_experimentalFeatures_get, "ConfigProtocolMock - stub value for experimentalFeatures was not defined") } - } - private var __p_experimentalFeatures: (ExperimentalFeaturesConfig)? - - public var URIScheme: String { - get { invocations.append(.p_URIScheme_get); return __p_URIScheme ?? givenGetterValue(.p_URIScheme_get, "ConfigProtocolMock - stub value for URIScheme was not defined") } - } - private var __p_URIScheme: (String)? - - - - - - - fileprivate enum MethodType { - case p_baseURL_get - case p_baseSSOURL_get - case p_ssoFinishedURL_get - case p_ssoButtonTitle_get - case p_oAuthClientId_get - case p_tokenType_get - case p_feedbackEmail_get - case p_appStoreLink_get - case p_faq_get - case p_platformName_get - case p_agreement_get - case p_firebase_get - case p_facebook_get - case p_microsoft_get - case p_google_get - case p_appleSignIn_get - case p_features_get - case p_theme_get - case p_uiComponents_get - case p_discovery_get - case p_dashboard_get - case p_braze_get - case p_branch_get - case p_program_get - case p_experimentalFeatures_get - case p_URIScheme_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_baseURL_get,.p_baseURL_get): return Matcher.ComparisonResult.match - case (.p_baseSSOURL_get,.p_baseSSOURL_get): return Matcher.ComparisonResult.match - case (.p_ssoFinishedURL_get,.p_ssoFinishedURL_get): return Matcher.ComparisonResult.match - case (.p_ssoButtonTitle_get,.p_ssoButtonTitle_get): return Matcher.ComparisonResult.match - case (.p_oAuthClientId_get,.p_oAuthClientId_get): return Matcher.ComparisonResult.match - case (.p_tokenType_get,.p_tokenType_get): return Matcher.ComparisonResult.match - case (.p_feedbackEmail_get,.p_feedbackEmail_get): return Matcher.ComparisonResult.match - case (.p_appStoreLink_get,.p_appStoreLink_get): return Matcher.ComparisonResult.match - case (.p_faq_get,.p_faq_get): return Matcher.ComparisonResult.match - case (.p_platformName_get,.p_platformName_get): return Matcher.ComparisonResult.match - case (.p_agreement_get,.p_agreement_get): return Matcher.ComparisonResult.match - case (.p_firebase_get,.p_firebase_get): return Matcher.ComparisonResult.match - case (.p_facebook_get,.p_facebook_get): return Matcher.ComparisonResult.match - case (.p_microsoft_get,.p_microsoft_get): return Matcher.ComparisonResult.match - case (.p_google_get,.p_google_get): return Matcher.ComparisonResult.match - case (.p_appleSignIn_get,.p_appleSignIn_get): return Matcher.ComparisonResult.match - case (.p_features_get,.p_features_get): return Matcher.ComparisonResult.match - case (.p_theme_get,.p_theme_get): return Matcher.ComparisonResult.match - case (.p_uiComponents_get,.p_uiComponents_get): return Matcher.ComparisonResult.match - case (.p_discovery_get,.p_discovery_get): return Matcher.ComparisonResult.match - case (.p_dashboard_get,.p_dashboard_get): return Matcher.ComparisonResult.match - case (.p_braze_get,.p_braze_get): return Matcher.ComparisonResult.match - case (.p_branch_get,.p_branch_get): return Matcher.ComparisonResult.match - case (.p_program_get,.p_program_get): return Matcher.ComparisonResult.match - case (.p_experimentalFeatures_get,.p_experimentalFeatures_get): return Matcher.ComparisonResult.match - case (.p_URIScheme_get,.p_URIScheme_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_baseURL_get: return 0 - case .p_baseSSOURL_get: return 0 - case .p_ssoFinishedURL_get: return 0 - case .p_ssoButtonTitle_get: return 0 - case .p_oAuthClientId_get: return 0 - case .p_tokenType_get: return 0 - case .p_feedbackEmail_get: return 0 - case .p_appStoreLink_get: return 0 - case .p_faq_get: return 0 - case .p_platformName_get: return 0 - case .p_agreement_get: return 0 - case .p_firebase_get: return 0 - case .p_facebook_get: return 0 - case .p_microsoft_get: return 0 - case .p_google_get: return 0 - case .p_appleSignIn_get: return 0 - case .p_features_get: return 0 - case .p_theme_get: return 0 - case .p_uiComponents_get: return 0 - case .p_discovery_get: return 0 - case .p_dashboard_get: return 0 - case .p_braze_get: return 0 - case .p_branch_get: return 0 - case .p_program_get: return 0 - case .p_experimentalFeatures_get: return 0 - case .p_URIScheme_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_baseURL_get: return "[get] .baseURL" - case .p_baseSSOURL_get: return "[get] .baseSSOURL" - case .p_ssoFinishedURL_get: return "[get] .ssoFinishedURL" - case .p_ssoButtonTitle_get: return "[get] .ssoButtonTitle" - case .p_oAuthClientId_get: return "[get] .oAuthClientId" - case .p_tokenType_get: return "[get] .tokenType" - case .p_feedbackEmail_get: return "[get] .feedbackEmail" - case .p_appStoreLink_get: return "[get] .appStoreLink" - case .p_faq_get: return "[get] .faq" - case .p_platformName_get: return "[get] .platformName" - case .p_agreement_get: return "[get] .agreement" - case .p_firebase_get: return "[get] .firebase" - case .p_facebook_get: return "[get] .facebook" - case .p_microsoft_get: return "[get] .microsoft" - case .p_google_get: return "[get] .google" - case .p_appleSignIn_get: return "[get] .appleSignIn" - case .p_features_get: return "[get] .features" - case .p_theme_get: return "[get] .theme" - case .p_uiComponents_get: return "[get] .uiComponents" - case .p_discovery_get: return "[get] .discovery" - case .p_dashboard_get: return "[get] .dashboard" - case .p_braze_get: return "[get] .braze" - case .p_branch_get: return "[get] .branch" - case .p_program_get: return "[get] .program" - case .p_experimentalFeatures_get: return "[get] .experimentalFeatures" - case .p_URIScheme_get: return "[get] .URIScheme" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func baseURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func baseSSOURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_baseSSOURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoFinishedURL(getter defaultValue: URL...) -> PropertyStub { - return Given(method: .p_ssoFinishedURL_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func ssoButtonTitle(getter defaultValue: [String: Any]...) -> PropertyStub { - return Given(method: .p_ssoButtonTitle_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func oAuthClientId(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_oAuthClientId_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func tokenType(getter defaultValue: TokenType...) -> PropertyStub { - return Given(method: .p_tokenType_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func feedbackEmail(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_feedbackEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appStoreLink(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_appStoreLink_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func faq(getter defaultValue: URL?...) -> PropertyStub { - return Given(method: .p_faq_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func platformName(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_platformName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func agreement(getter defaultValue: AgreementConfig...) -> PropertyStub { - return Given(method: .p_agreement_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func firebase(getter defaultValue: FirebaseConfig...) -> PropertyStub { - return Given(method: .p_firebase_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func facebook(getter defaultValue: FacebookConfig...) -> PropertyStub { - return Given(method: .p_facebook_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func microsoft(getter defaultValue: MicrosoftConfig...) -> PropertyStub { - return Given(method: .p_microsoft_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func google(getter defaultValue: GoogleConfig...) -> PropertyStub { - return Given(method: .p_google_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignIn(getter defaultValue: AppleSignInConfig...) -> PropertyStub { - return Given(method: .p_appleSignIn_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func features(getter defaultValue: FeaturesConfig...) -> PropertyStub { - return Given(method: .p_features_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func theme(getter defaultValue: ThemeConfig...) -> PropertyStub { - return Given(method: .p_theme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func uiComponents(getter defaultValue: UIComponentsConfig...) -> PropertyStub { - return Given(method: .p_uiComponents_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func discovery(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_discovery_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func dashboard(getter defaultValue: DashboardConfig...) -> PropertyStub { - return Given(method: .p_dashboard_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func braze(getter defaultValue: BrazeConfig...) -> PropertyStub { - return Given(method: .p_braze_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func branch(getter defaultValue: BranchConfig...) -> PropertyStub { - return Given(method: .p_branch_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func program(getter defaultValue: DiscoveryConfig...) -> PropertyStub { - return Given(method: .p_program_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func experimentalFeatures(getter defaultValue: ExperimentalFeaturesConfig...) -> PropertyStub { - return Given(method: .p_experimentalFeatures_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func URIScheme(getter defaultValue: String...) -> PropertyStub { - return Given(method: .p_URIScheme_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var baseURL: Verify { return Verify(method: .p_baseURL_get) } - public static var baseSSOURL: Verify { return Verify(method: .p_baseSSOURL_get) } - public static var ssoFinishedURL: Verify { return Verify(method: .p_ssoFinishedURL_get) } - public static var ssoButtonTitle: Verify { return Verify(method: .p_ssoButtonTitle_get) } - public static var oAuthClientId: Verify { return Verify(method: .p_oAuthClientId_get) } - public static var tokenType: Verify { return Verify(method: .p_tokenType_get) } - public static var feedbackEmail: Verify { return Verify(method: .p_feedbackEmail_get) } - public static var appStoreLink: Verify { return Verify(method: .p_appStoreLink_get) } - public static var faq: Verify { return Verify(method: .p_faq_get) } - public static var platformName: Verify { return Verify(method: .p_platformName_get) } - public static var agreement: Verify { return Verify(method: .p_agreement_get) } - public static var firebase: Verify { return Verify(method: .p_firebase_get) } - public static var facebook: Verify { return Verify(method: .p_facebook_get) } - public static var microsoft: Verify { return Verify(method: .p_microsoft_get) } - public static var google: Verify { return Verify(method: .p_google_get) } - public static var appleSignIn: Verify { return Verify(method: .p_appleSignIn_get) } - public static var features: Verify { return Verify(method: .p_features_get) } - public static var theme: Verify { return Verify(method: .p_theme_get) } - public static var uiComponents: Verify { return Verify(method: .p_uiComponents_get) } - public static var discovery: Verify { return Verify(method: .p_discovery_get) } - public static var dashboard: Verify { return Verify(method: .p_dashboard_get) } - public static var braze: Verify { return Verify(method: .p_braze_get) } - public static var branch: Verify { return Verify(method: .p_branch_get) } - public static var program: Verify { return Verify(method: .p_program_get) } - public static var experimentalFeatures: Verify { return Verify(method: .p_experimentalFeatures_get) } - public static var URIScheme: Verify { return Verify(method: .p_URIScheme_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ConnectivityProtocol -@MainActor -open class ConnectivityProtocolMock: ConnectivityProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var isInternetAvaliable: Bool { - get { invocations.append(.p_isInternetAvaliable_get); return __p_isInternetAvaliable ?? givenGetterValue(.p_isInternetAvaliable_get, "ConnectivityProtocolMock - stub value for isInternetAvaliable was not defined") } - } - private var __p_isInternetAvaliable: (Bool)? - - public var isMobileData: Bool { - get { invocations.append(.p_isMobileData_get); return __p_isMobileData ?? givenGetterValue(.p_isMobileData_get, "ConnectivityProtocolMock - stub value for isMobileData was not defined") } - } - private var __p_isMobileData: (Bool)? - - public var internetReachableSubject: CurrentValueSubject { - get { invocations.append(.p_internetReachableSubject_get); return __p_internetReachableSubject ?? givenGetterValue(.p_internetReachableSubject_get, "ConnectivityProtocolMock - stub value for internetReachableSubject was not defined") } - } - private var __p_internetReachableSubject: (CurrentValueSubject)? - - - - - - - fileprivate enum MethodType { - case p_isInternetAvaliable_get - case p_isMobileData_get - case p_internetReachableSubject_get - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_isInternetAvaliable_get,.p_isInternetAvaliable_get): return Matcher.ComparisonResult.match - case (.p_isMobileData_get,.p_isMobileData_get): return Matcher.ComparisonResult.match - case (.p_internetReachableSubject_get,.p_internetReachableSubject_get): return Matcher.ComparisonResult.match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_isInternetAvaliable_get: return 0 - case .p_isMobileData_get: return 0 - case .p_internetReachableSubject_get: return 0 - } - } - func assertionName() -> String { - switch self { - case .p_isInternetAvaliable_get: return "[get] .isInternetAvaliable" - case .p_isMobileData_get: return "[get] .isMobileData" - case .p_internetReachableSubject_get: return "[get] .internetReachableSubject" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func isInternetAvaliable(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isInternetAvaliable_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func isMobileData(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_isMobileData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func internetReachableSubject(getter defaultValue: CurrentValueSubject...) -> PropertyStub { - return Given(method: .p_internetReachableSubject_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var isInternetAvaliable: Verify { return Verify(method: .p_isInternetAvaliable_get) } - public static var isMobileData: Verify { return Verify(method: .p_isMobileData_get) } - public static var internetReachableSubject: Verify { return Verify(method: .p_internetReachableSubject_get) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreAnalytics - -open class CoreAnalyticsMock: CoreAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func trackEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventparameters_parameters(Parameter.value(`event`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, [String: Any]?) -> Void - perform?(`event`, `parameters`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue, parameters: [String: Any]?) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter.value(`event`), Parameter.value(`biValue`), Parameter<[String: Any]?>.value(`parameters`))) as? (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void - perform?(`event`, `biValue`, `parameters`) - } - - open func appreview(_ event: AnalyticsEvent, biValue: EventBIValue, action: String?, rating: Int?) { - addInvocation(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) - let perform = methodPerformValue(.m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter.value(`event`), Parameter.value(`biValue`), Parameter.value(`action`), Parameter.value(`rating`))) as? (AnalyticsEvent, EventBIValue, String?, Int?) -> Void - perform?(`event`, `biValue`, `action`, `rating`) - } - - open func videoQualityChanged(_ event: AnalyticsEvent, bivalue: EventBIValue, value: String, oldValue: String) { - addInvocation(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) - let perform = methodPerformValue(.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter.value(`event`), Parameter.value(`bivalue`), Parameter.value(`value`), Parameter.value(`oldValue`))) as? (AnalyticsEvent, EventBIValue, String, String) -> Void - perform?(`event`, `bivalue`, `value`, `oldValue`) - } - - open func trackEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent) { - addInvocation(.m_trackScreenEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_trackScreenEvent__event(Parameter.value(`event`))) as? (AnalyticsEvent) -> Void - perform?(`event`) - } - - open func trackScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_trackScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - - fileprivate enum MethodType { - case m_trackEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventparameters_parameters(Parameter, Parameter<[String: Any]?>) - case m_trackScreenEvent__eventbiValue_biValueparameters_parameters(Parameter, Parameter, Parameter<[String: Any]?>) - case m_appreview__eventbiValue_biValueaction_actionrating_rating(Parameter, Parameter, Parameter, Parameter) - case m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(Parameter, Parameter, Parameter, Parameter) - case m_trackEvent__event(Parameter) - case m_trackEvent__eventbiValue_biValue(Parameter, Parameter) - case m_trackScreenEvent__event(Parameter) - case m_trackScreenEvent__eventbiValue_biValue(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_trackEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventparameters_parameters(let lhsEvent, let lhsParameters), .m_trackScreenEvent__eventparameters_parameters(let rhsEvent, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let lhsEvent, let lhsBivalue, let lhsParameters), .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(let rhsEvent, let rhsBivalue, let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_appreview__eventbiValue_biValueaction_actionrating_rating(let lhsEvent, let lhsBivalue, let lhsAction, let lhsRating), .m_appreview__eventbiValue_biValueaction_actionrating_rating(let rhsEvent, let rhsBivalue, let rhsAction, let rhsRating)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsRating, rhs: rhsRating, with: matcher), lhsRating, rhsRating, "rating")) - return Matcher.ComparisonResult(results) - - case (.m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let lhsEvent, let lhsBivalue, let lhsValue, let lhsOldvalue), .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(let rhsEvent, let rhsBivalue, let rhsValue, let rhsOldvalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "bivalue")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsValue, rhs: rhsValue, with: matcher), lhsValue, rhsValue, "value")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOldvalue, rhs: rhsOldvalue, with: matcher), lhsOldvalue, rhsOldvalue, "oldValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__event(let lhsEvent), .m_trackEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__event(let lhsEvent), .m_trackScreenEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_trackScreenEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_trackScreenEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_trackEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_trackScreenEvent__eventparameters_parameters(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_appreview__eventbiValue_biValueaction_actionrating_rating(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(p0, p1, p2, p3): return p0.intValue + p1.intValue + p2.intValue + p3.intValue - case let .m_trackEvent__event(p0): return p0.intValue - case let .m_trackEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - case let .m_trackScreenEvent__event(p0): return p0.intValue - case let .m_trackScreenEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_trackEvent__eventparameters_parameters: return ".trackEvent(_:parameters:)" - case .m_trackEvent__eventbiValue_biValueparameters_parameters: return ".trackEvent(_:biValue:parameters:)" - case .m_trackScreenEvent__eventparameters_parameters: return ".trackScreenEvent(_:parameters:)" - case .m_trackScreenEvent__eventbiValue_biValueparameters_parameters: return ".trackScreenEvent(_:biValue:parameters:)" - case .m_appreview__eventbiValue_biValueaction_actionrating_rating: return ".appreview(_:biValue:action:rating:)" - case .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue: return ".videoQualityChanged(_:bivalue:value:oldValue:)" - case .m_trackEvent__event: return ".trackEvent(_:)" - case .m_trackEvent__eventbiValue_biValue: return ".trackEvent(_:biValue:)" - case .m_trackScreenEvent__event: return ".trackScreenEvent(_:)" - case .m_trackScreenEvent__eventbiValue_biValue: return ".trackScreenEvent(_:biValue:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`))} - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter) -> Verify { return Verify(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`))} - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter) -> Verify { return Verify(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`))} - public static func trackEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackEvent__event(`event`))} - public static func trackEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`))} - public static func trackScreenEvent(_ event: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__event(`event`))} - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func trackEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventparameters_parameters(`event`, `parameters`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, parameters: Parameter<[String: Any]?>, perform: @escaping (AnalyticsEvent, EventBIValue, [String: Any]?) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValueparameters_parameters(`event`, `biValue`, `parameters`), performs: perform) - } - public static func appreview(_ event: Parameter, biValue: Parameter, action: Parameter, rating: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String?, Int?) -> Void) -> Perform { - return Perform(method: .m_appreview__eventbiValue_biValueaction_actionrating_rating(`event`, `biValue`, `action`, `rating`), performs: perform) - } - public static func videoQualityChanged(_ event: Parameter, bivalue: Parameter, value: Parameter, oldValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue, String, String) -> Void) -> Perform { - return Perform(method: .m_videoQualityChanged__eventbivalue_bivaluevalue_valueoldValue_oldValue(`event`, `bivalue`, `value`, `oldValue`), performs: perform) - } - public static func trackEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackEvent__event(`event`), performs: perform) - } - public static func trackEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, perform: @escaping (AnalyticsEvent) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__event(`event`), performs: perform) - } - public static func trackScreenEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_trackScreenEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CorePersistenceProtocol - -open class CorePersistenceProtocolMock: CorePersistenceProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func set(userId: Int) { - addInvocation(.m_set__userId_userId(Parameter.value(`userId`))) - let perform = methodPerformValue(.m_set__userId_userId(Parameter.value(`userId`))) as? (Int) -> Void - perform?(`userId`) - } - - open func getUserID() -> Int? { - addInvocation(.m_getUserID) - let perform = methodPerformValue(.m_getUserID) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getUserID).casted() - } catch { - // do nothing - } - return __value - } - - @MainActor - open func publisher() throws -> AnyPublisher { - addInvocation(.m_publisher) - let perform = methodPerformValue(.m_publisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_publisher).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for publisher(). Use given") - Failure("Stub return value not specified for publisher(). Use given") - } catch { - throw error - } - return __value - } - - open func addToDownloadQueue(tasks: [DownloadDataTask]) { - addInvocation(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>.value(`tasks`))) as? ([DownloadDataTask]) -> Void - perform?(`tasks`) - } - - open func saveOfflineProgress(progress: OfflineProgress) { - addInvocation(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) - let perform = methodPerformValue(.m_saveOfflineProgress__progress_progress(Parameter.value(`progress`))) as? (OfflineProgress) -> Void - perform?(`progress`) - } - - open func loadProgress(for blockID: String) -> OfflineProgress? { - addInvocation(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - var __value: OfflineProgress? = nil - do { - __value = try methodReturnValue(.m_loadProgress__for_blockID(Parameter.value(`blockID`))).casted() - } catch { - // do nothing - } - return __value - } - - open func loadAllOfflineProgress() -> [OfflineProgress] { - addInvocation(.m_loadAllOfflineProgress) - let perform = methodPerformValue(.m_loadAllOfflineProgress) as? () -> Void - perform?() - var __value: [OfflineProgress] - do { - __value = try methodReturnValue(.m_loadAllOfflineProgress).casted() - } catch { - onFatalFailure("Stub return value not specified for loadAllOfflineProgress(). Use given") - Failure("Stub return value not specified for loadAllOfflineProgress(). Use given") - } - return __value - } - - open func deleteProgress(for blockID: String) { - addInvocation(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) - let perform = methodPerformValue(.m_deleteProgress__for_blockID(Parameter.value(`blockID`))) as? (String) -> Void - perform?(`blockID`) - } - - open func deleteAllProgress() { - addInvocation(.m_deleteAllProgress) - let perform = methodPerformValue(.m_deleteAllProgress) as? () -> Void - perform?() - } - - open func addToDownloadQueue(blocks: [CourseBlock], downloadQuality: DownloadQuality) { - addInvocation(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`downloadQuality`))) as? ([CourseBlock], DownloadQuality) -> Void - perform?(`blocks`, `downloadQuality`) - } - - open func updateTask(task: DownloadDataTask) { - addInvocation(.m_updateTask__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_updateTask__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - } - - open func downloadDataTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadDataTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getDownloadDataTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasks) - let perform = methodPerformValue(.m_getDownloadDataTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasks(). Use given") - Failure("Stub return value not specified for getDownloadDataTasks(). Use given") - } - return __value - } - - open func getDownloadDataTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadDataTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadDataTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func deleteDownloadDataTasks(ids: [String]) { - addInvocation(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) - let perform = methodPerformValue(.m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>.value(`ids`))) as? ([String]) -> Void - perform?(`ids`) - } - - - fileprivate enum MethodType { - case m_set__userId_userId(Parameter) - case m_getUserID - case m_publisher - case m_addToDownloadQueue__tasks_tasks(Parameter<[DownloadDataTask]>) - case m_saveOfflineProgress__progress_progress(Parameter) - case m_loadProgress__for_blockID(Parameter) - case m_loadAllOfflineProgress - case m_deleteProgress__for_blockID(Parameter) - case m_deleteAllProgress - case m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(Parameter<[CourseBlock]>, Parameter) - case m_updateTask__task_task(Parameter) - case m_downloadDataTask__for_blockId(Parameter) - case m_getDownloadDataTasks - case m_getDownloadDataTasksForCourse__courseId(Parameter) - case m_deleteDownloadDataTasks__ids_ids(Parameter<[String]>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_set__userId_userId(let lhsUserid), .m_set__userId_userId(let rhsUserid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUserid, rhs: rhsUserid, with: matcher), lhsUserid, rhsUserid, "userId")) - return Matcher.ComparisonResult(results) - - case (.m_getUserID, .m_getUserID): return .match - - case (.m_publisher, .m_publisher): return .match - - case (.m_addToDownloadQueue__tasks_tasks(let lhsTasks), .m_addToDownloadQueue__tasks_tasks(let rhsTasks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTasks, rhs: rhsTasks, with: matcher), lhsTasks, rhsTasks, "tasks")) - return Matcher.ComparisonResult(results) - - case (.m_saveOfflineProgress__progress_progress(let lhsProgress), .m_saveOfflineProgress__progress_progress(let rhsProgress)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsProgress, rhs: rhsProgress, with: matcher), lhsProgress, rhsProgress, "progress")) - return Matcher.ComparisonResult(results) - - case (.m_loadProgress__for_blockID(let lhsBlockid), .m_loadProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_loadAllOfflineProgress, .m_loadAllOfflineProgress): return .match - - case (.m_deleteProgress__for_blockID(let lhsBlockid), .m_deleteProgress__for_blockID(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockID")) - return Matcher.ComparisonResult(results) - - case (.m_deleteAllProgress, .m_deleteAllProgress): return .match - - case (.m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let lhsBlocks, let lhsDownloadquality), .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(let rhsBlocks, let rhsDownloadquality)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadquality, rhs: rhsDownloadquality, with: matcher), lhsDownloadquality, rhsDownloadquality, "downloadQuality")) - return Matcher.ComparisonResult(results) - - case (.m_updateTask__task_task(let lhsTask), .m_updateTask__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_downloadDataTask__for_blockId(let lhsBlockid), .m_downloadDataTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadDataTasks, .m_getDownloadDataTasks): return .match - - case (.m_getDownloadDataTasksForCourse__courseId(let lhsCourseid), .m_getDownloadDataTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_deleteDownloadDataTasks__ids_ids(let lhsIds), .m_deleteDownloadDataTasks__ids_ids(let rhsIds)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsIds, rhs: rhsIds, with: matcher), lhsIds, rhsIds, "ids")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_set__userId_userId(p0): return p0.intValue - case .m_getUserID: return 0 - case .m_publisher: return 0 - case let .m_addToDownloadQueue__tasks_tasks(p0): return p0.intValue - case let .m_saveOfflineProgress__progress_progress(p0): return p0.intValue - case let .m_loadProgress__for_blockID(p0): return p0.intValue - case .m_loadAllOfflineProgress: return 0 - case let .m_deleteProgress__for_blockID(p0): return p0.intValue - case .m_deleteAllProgress: return 0 - case let .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(p0, p1): return p0.intValue + p1.intValue - case let .m_updateTask__task_task(p0): return p0.intValue - case let .m_downloadDataTask__for_blockId(p0): return p0.intValue - case .m_getDownloadDataTasks: return 0 - case let .m_getDownloadDataTasksForCourse__courseId(p0): return p0.intValue - case let .m_deleteDownloadDataTasks__ids_ids(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_set__userId_userId: return ".set(userId:)" - case .m_getUserID: return ".getUserID()" - case .m_publisher: return ".publisher()" - case .m_addToDownloadQueue__tasks_tasks: return ".addToDownloadQueue(tasks:)" - case .m_saveOfflineProgress__progress_progress: return ".saveOfflineProgress(progress:)" - case .m_loadProgress__for_blockID: return ".loadProgress(for:)" - case .m_loadAllOfflineProgress: return ".loadAllOfflineProgress()" - case .m_deleteProgress__for_blockID: return ".deleteProgress(for:)" - case .m_deleteAllProgress: return ".deleteAllProgress()" - case .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality: return ".addToDownloadQueue(blocks:downloadQuality:)" - case .m_updateTask__task_task: return ".updateTask(task:)" - case .m_downloadDataTask__for_blockId: return ".downloadDataTask(for:)" - case .m_getDownloadDataTasks: return ".getDownloadDataTasks()" - case .m_getDownloadDataTasksForCourse__courseId: return ".getDownloadDataTasksForCourse(_:)" - case .m_deleteDownloadDataTasks__ids_ids: return ".deleteDownloadDataTasks(ids:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getUserID(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - @MainActor - public static func publisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_publisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadProgress(for blockID: Parameter, willReturn: OfflineProgress?...) -> MethodStub { - return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func loadAllOfflineProgress(willReturn: [OfflineProgress]...) -> MethodStub { - return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadDataTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getUserID(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getUserID, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func loadProgress(for blockID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [OfflineProgress?] = [] - let given: Given = { return Given(method: .m_loadProgress__for_blockID(`blockID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (OfflineProgress?).self) - willProduce(stubber) - return given - } - public static func loadAllOfflineProgress(willProduce: (Stubber<[OfflineProgress]>) -> Void) -> MethodStub { - let willReturn: [[OfflineProgress]] = [] - let given: Given = { return Given(method: .m_loadAllOfflineProgress, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([OfflineProgress]).self) - willProduce(stubber) - return given - } - public static func downloadDataTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadDataTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - @MainActor - public static func publisher(willThrow: Error...) -> MethodStub { - return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) - } - @MainActor - public static func publisher(willProduce: (StubberThrows>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_publisher, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func set(userId: Parameter) -> Verify { return Verify(method: .m_set__userId_userId(`userId`))} - public static func getUserID() -> Verify { return Verify(method: .m_getUserID)} - @MainActor - public static func publisher() -> Verify { return Verify(method: .m_publisher)} - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>) -> Verify { return Verify(method: .m_addToDownloadQueue__tasks_tasks(`tasks`))} - public static func saveOfflineProgress(progress: Parameter) -> Verify { return Verify(method: .m_saveOfflineProgress__progress_progress(`progress`))} - public static func loadProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_loadProgress__for_blockID(`blockID`))} - public static func loadAllOfflineProgress() -> Verify { return Verify(method: .m_loadAllOfflineProgress)} - public static func deleteProgress(for blockID: Parameter) -> Verify { return Verify(method: .m_deleteProgress__for_blockID(`blockID`))} - public static func deleteAllProgress() -> Verify { return Verify(method: .m_deleteAllProgress)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`))} - public static func updateTask(task: Parameter) -> Verify { return Verify(method: .m_updateTask__task_task(`task`))} - public static func downloadDataTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadDataTask__for_blockId(`blockId`))} - public static func getDownloadDataTasks() -> Verify { return Verify(method: .m_getDownloadDataTasks)} - public static func getDownloadDataTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`))} - public static func deleteDownloadDataTasks(ids: Parameter<[String]>) -> Verify { return Verify(method: .m_deleteDownloadDataTasks__ids_ids(`ids`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func set(userId: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_set__userId_userId(`userId`), performs: perform) - } - public static func getUserID(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getUserID, performs: perform) - } - @MainActor - public static func publisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_publisher, performs: perform) - } - public static func addToDownloadQueue(tasks: Parameter<[DownloadDataTask]>, perform: @escaping ([DownloadDataTask]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__tasks_tasks(`tasks`), performs: perform) - } - public static func saveOfflineProgress(progress: Parameter, perform: @escaping (OfflineProgress) -> Void) -> Perform { - return Perform(method: .m_saveOfflineProgress__progress_progress(`progress`), performs: perform) - } - public static func loadProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_loadProgress__for_blockID(`blockID`), performs: perform) - } - public static func loadAllOfflineProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_loadAllOfflineProgress, performs: perform) - } - public static func deleteProgress(for blockID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_deleteProgress__for_blockID(`blockID`), performs: perform) - } - public static func deleteAllProgress(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAllProgress, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, downloadQuality: Parameter, perform: @escaping ([CourseBlock], DownloadQuality) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocksdownloadQuality_downloadQuality(`blocks`, `downloadQuality`), performs: perform) - } - public static func updateTask(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_updateTask__task_task(`task`), performs: perform) - } - public static func downloadDataTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadDataTask__for_blockId(`blockId`), performs: perform) - } - public static func getDownloadDataTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasks, performs: perform) - } - public static func getDownloadDataTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadDataTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func deleteDownloadDataTasks(ids: Parameter<[String]>, perform: @escaping ([String]) -> Void) -> Perform { - return Perform(method: .m_deleteDownloadDataTasks__ids_ids(`ids`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CoreStorage - -open class CoreStorageMock: CoreStorage, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var accessToken: String? { - get { invocations.append(.p_accessToken_get); return __p_accessToken ?? optionalGivenGetterValue(.p_accessToken_get, "CoreStorageMock - stub value for accessToken was not defined") } - set { invocations.append(.p_accessToken_set(.value(newValue))); __p_accessToken = newValue } - } - private var __p_accessToken: (String)? - - public var refreshToken: String? { - get { invocations.append(.p_refreshToken_get); return __p_refreshToken ?? optionalGivenGetterValue(.p_refreshToken_get, "CoreStorageMock - stub value for refreshToken was not defined") } - set { invocations.append(.p_refreshToken_set(.value(newValue))); __p_refreshToken = newValue } - } - private var __p_refreshToken: (String)? - - public var pushToken: String? { - get { invocations.append(.p_pushToken_get); return __p_pushToken ?? optionalGivenGetterValue(.p_pushToken_get, "CoreStorageMock - stub value for pushToken was not defined") } - set { invocations.append(.p_pushToken_set(.value(newValue))); __p_pushToken = newValue } - } - private var __p_pushToken: (String)? - - public var appleSignFullName: String? { - get { invocations.append(.p_appleSignFullName_get); return __p_appleSignFullName ?? optionalGivenGetterValue(.p_appleSignFullName_get, "CoreStorageMock - stub value for appleSignFullName was not defined") } - set { invocations.append(.p_appleSignFullName_set(.value(newValue))); __p_appleSignFullName = newValue } - } - private var __p_appleSignFullName: (String)? - - public var appleSignEmail: String? { - get { invocations.append(.p_appleSignEmail_get); return __p_appleSignEmail ?? optionalGivenGetterValue(.p_appleSignEmail_get, "CoreStorageMock - stub value for appleSignEmail was not defined") } - set { invocations.append(.p_appleSignEmail_set(.value(newValue))); __p_appleSignEmail = newValue } - } - private var __p_appleSignEmail: (String)? - - public var cookiesDate: Date? { - get { invocations.append(.p_cookiesDate_get); return __p_cookiesDate ?? optionalGivenGetterValue(.p_cookiesDate_get, "CoreStorageMock - stub value for cookiesDate was not defined") } - set { invocations.append(.p_cookiesDate_set(.value(newValue))); __p_cookiesDate = newValue } - } - private var __p_cookiesDate: (Date)? - - public var reviewLastShownVersion: String? { - get { invocations.append(.p_reviewLastShownVersion_get); return __p_reviewLastShownVersion ?? optionalGivenGetterValue(.p_reviewLastShownVersion_get, "CoreStorageMock - stub value for reviewLastShownVersion was not defined") } - set { invocations.append(.p_reviewLastShownVersion_set(.value(newValue))); __p_reviewLastShownVersion = newValue } - } - private var __p_reviewLastShownVersion: (String)? - - public var lastReviewDate: Date? { - get { invocations.append(.p_lastReviewDate_get); return __p_lastReviewDate ?? optionalGivenGetterValue(.p_lastReviewDate_get, "CoreStorageMock - stub value for lastReviewDate was not defined") } - set { invocations.append(.p_lastReviewDate_set(.value(newValue))); __p_lastReviewDate = newValue } - } - private var __p_lastReviewDate: (Date)? - - public var user: DataLayer.User? { - get { invocations.append(.p_user_get); return __p_user ?? optionalGivenGetterValue(.p_user_get, "CoreStorageMock - stub value for user was not defined") } - set { invocations.append(.p_user_set(.value(newValue))); __p_user = newValue } - } - private var __p_user: (DataLayer.User)? - - public var userSettings: UserSettings? { - get { invocations.append(.p_userSettings_get); return __p_userSettings ?? optionalGivenGetterValue(.p_userSettings_get, "CoreStorageMock - stub value for userSettings was not defined") } - set { invocations.append(.p_userSettings_set(.value(newValue))); __p_userSettings = newValue } - } - private var __p_userSettings: (UserSettings)? - - public var resetAppSupportDirectoryUserData: Bool? { - get { invocations.append(.p_resetAppSupportDirectoryUserData_get); return __p_resetAppSupportDirectoryUserData ?? optionalGivenGetterValue(.p_resetAppSupportDirectoryUserData_get, "CoreStorageMock - stub value for resetAppSupportDirectoryUserData was not defined") } - set { invocations.append(.p_resetAppSupportDirectoryUserData_set(.value(newValue))); __p_resetAppSupportDirectoryUserData = newValue } - } - private var __p_resetAppSupportDirectoryUserData: (Bool)? - - public var useRelativeDates: Bool { - get { invocations.append(.p_useRelativeDates_get); return __p_useRelativeDates ?? givenGetterValue(.p_useRelativeDates_get, "CoreStorageMock - stub value for useRelativeDates was not defined") } - set { invocations.append(.p_useRelativeDates_set(.value(newValue))); __p_useRelativeDates = newValue } - } - private var __p_useRelativeDates: (Bool)? - - public var lastUsedSocialAuth: String? { - get { invocations.append(.p_lastUsedSocialAuth_get); return __p_lastUsedSocialAuth ?? optionalGivenGetterValue(.p_lastUsedSocialAuth_get, "CoreStorageMock - stub value for lastUsedSocialAuth was not defined") } - set { invocations.append(.p_lastUsedSocialAuth_set(.value(newValue))); __p_lastUsedSocialAuth = newValue } - } - private var __p_lastUsedSocialAuth: (String)? - - public var latestAvailableAppVersion: String? { - get { invocations.append(.p_latestAvailableAppVersion_get); return __p_latestAvailableAppVersion ?? optionalGivenGetterValue(.p_latestAvailableAppVersion_get, "CoreStorageMock - stub value for latestAvailableAppVersion was not defined") } - set { invocations.append(.p_latestAvailableAppVersion_set(.value(newValue))); __p_latestAvailableAppVersion = newValue } - } - private var __p_latestAvailableAppVersion: (String)? - - public var updateAppRequired: Bool { - get { invocations.append(.p_updateAppRequired_get); return __p_updateAppRequired ?? givenGetterValue(.p_updateAppRequired_get, "CoreStorageMock - stub value for updateAppRequired was not defined") } - set { invocations.append(.p_updateAppRequired_set(.value(newValue))); __p_updateAppRequired = newValue } - } - private var __p_updateAppRequired: (Bool)? - - - - - - open func clear() { - addInvocation(.m_clear) - let perform = methodPerformValue(.m_clear) as? () -> Void - perform?() - } - - - fileprivate enum MethodType { - case m_clear - case p_accessToken_get - case p_accessToken_set(Parameter) - case p_refreshToken_get - case p_refreshToken_set(Parameter) - case p_pushToken_get - case p_pushToken_set(Parameter) - case p_appleSignFullName_get - case p_appleSignFullName_set(Parameter) - case p_appleSignEmail_get - case p_appleSignEmail_set(Parameter) - case p_cookiesDate_get - case p_cookiesDate_set(Parameter) - case p_reviewLastShownVersion_get - case p_reviewLastShownVersion_set(Parameter) - case p_lastReviewDate_get - case p_lastReviewDate_set(Parameter) - case p_user_get - case p_user_set(Parameter) - case p_userSettings_get - case p_userSettings_set(Parameter) - case p_resetAppSupportDirectoryUserData_get - case p_resetAppSupportDirectoryUserData_set(Parameter) - case p_useRelativeDates_get - case p_useRelativeDates_set(Parameter) - case p_lastUsedSocialAuth_get - case p_lastUsedSocialAuth_set(Parameter) - case p_latestAvailableAppVersion_get - case p_latestAvailableAppVersion_set(Parameter) - case p_updateAppRequired_get - case p_updateAppRequired_set(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_clear, .m_clear): return .match - case (.p_accessToken_get,.p_accessToken_get): return Matcher.ComparisonResult.match - case (.p_accessToken_set(let left),.p_accessToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_refreshToken_get,.p_refreshToken_get): return Matcher.ComparisonResult.match - case (.p_refreshToken_set(let left),.p_refreshToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_pushToken_get,.p_pushToken_get): return Matcher.ComparisonResult.match - case (.p_pushToken_set(let left),.p_pushToken_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignFullName_get,.p_appleSignFullName_get): return Matcher.ComparisonResult.match - case (.p_appleSignFullName_set(let left),.p_appleSignFullName_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_appleSignEmail_get,.p_appleSignEmail_get): return Matcher.ComparisonResult.match - case (.p_appleSignEmail_set(let left),.p_appleSignEmail_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_cookiesDate_get,.p_cookiesDate_get): return Matcher.ComparisonResult.match - case (.p_cookiesDate_set(let left),.p_cookiesDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_reviewLastShownVersion_get,.p_reviewLastShownVersion_get): return Matcher.ComparisonResult.match - case (.p_reviewLastShownVersion_set(let left),.p_reviewLastShownVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastReviewDate_get,.p_lastReviewDate_get): return Matcher.ComparisonResult.match - case (.p_lastReviewDate_set(let left),.p_lastReviewDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_user_get,.p_user_get): return Matcher.ComparisonResult.match - case (.p_user_set(let left),.p_user_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_userSettings_get,.p_userSettings_get): return Matcher.ComparisonResult.match - case (.p_userSettings_set(let left),.p_userSettings_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_resetAppSupportDirectoryUserData_get,.p_resetAppSupportDirectoryUserData_get): return Matcher.ComparisonResult.match - case (.p_resetAppSupportDirectoryUserData_set(let left),.p_resetAppSupportDirectoryUserData_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_useRelativeDates_get,.p_useRelativeDates_get): return Matcher.ComparisonResult.match - case (.p_useRelativeDates_set(let left),.p_useRelativeDates_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastUsedSocialAuth_get,.p_lastUsedSocialAuth_get): return Matcher.ComparisonResult.match - case (.p_lastUsedSocialAuth_set(let left),.p_lastUsedSocialAuth_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_latestAvailableAppVersion_get,.p_latestAvailableAppVersion_get): return Matcher.ComparisonResult.match - case (.p_latestAvailableAppVersion_set(let left),.p_latestAvailableAppVersion_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_updateAppRequired_get,.p_updateAppRequired_get): return Matcher.ComparisonResult.match - case (.p_updateAppRequired_set(let left),.p_updateAppRequired_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_clear: return 0 - case .p_accessToken_get: return 0 - case .p_accessToken_set(let newValue): return newValue.intValue - case .p_refreshToken_get: return 0 - case .p_refreshToken_set(let newValue): return newValue.intValue - case .p_pushToken_get: return 0 - case .p_pushToken_set(let newValue): return newValue.intValue - case .p_appleSignFullName_get: return 0 - case .p_appleSignFullName_set(let newValue): return newValue.intValue - case .p_appleSignEmail_get: return 0 - case .p_appleSignEmail_set(let newValue): return newValue.intValue - case .p_cookiesDate_get: return 0 - case .p_cookiesDate_set(let newValue): return newValue.intValue - case .p_reviewLastShownVersion_get: return 0 - case .p_reviewLastShownVersion_set(let newValue): return newValue.intValue - case .p_lastReviewDate_get: return 0 - case .p_lastReviewDate_set(let newValue): return newValue.intValue - case .p_user_get: return 0 - case .p_user_set(let newValue): return newValue.intValue - case .p_userSettings_get: return 0 - case .p_userSettings_set(let newValue): return newValue.intValue - case .p_resetAppSupportDirectoryUserData_get: return 0 - case .p_resetAppSupportDirectoryUserData_set(let newValue): return newValue.intValue - case .p_useRelativeDates_get: return 0 - case .p_useRelativeDates_set(let newValue): return newValue.intValue - case .p_lastUsedSocialAuth_get: return 0 - case .p_lastUsedSocialAuth_set(let newValue): return newValue.intValue - case .p_latestAvailableAppVersion_get: return 0 - case .p_latestAvailableAppVersion_set(let newValue): return newValue.intValue - case .p_updateAppRequired_get: return 0 - case .p_updateAppRequired_set(let newValue): return newValue.intValue - } - } - func assertionName() -> String { - switch self { - case .m_clear: return ".clear()" - case .p_accessToken_get: return "[get] .accessToken" - case .p_accessToken_set: return "[set] .accessToken" - case .p_refreshToken_get: return "[get] .refreshToken" - case .p_refreshToken_set: return "[set] .refreshToken" - case .p_pushToken_get: return "[get] .pushToken" - case .p_pushToken_set: return "[set] .pushToken" - case .p_appleSignFullName_get: return "[get] .appleSignFullName" - case .p_appleSignFullName_set: return "[set] .appleSignFullName" - case .p_appleSignEmail_get: return "[get] .appleSignEmail" - case .p_appleSignEmail_set: return "[set] .appleSignEmail" - case .p_cookiesDate_get: return "[get] .cookiesDate" - case .p_cookiesDate_set: return "[set] .cookiesDate" - case .p_reviewLastShownVersion_get: return "[get] .reviewLastShownVersion" - case .p_reviewLastShownVersion_set: return "[set] .reviewLastShownVersion" - case .p_lastReviewDate_get: return "[get] .lastReviewDate" - case .p_lastReviewDate_set: return "[set] .lastReviewDate" - case .p_user_get: return "[get] .user" - case .p_user_set: return "[set] .user" - case .p_userSettings_get: return "[get] .userSettings" - case .p_userSettings_set: return "[set] .userSettings" - case .p_resetAppSupportDirectoryUserData_get: return "[get] .resetAppSupportDirectoryUserData" - case .p_resetAppSupportDirectoryUserData_set: return "[set] .resetAppSupportDirectoryUserData" - case .p_useRelativeDates_get: return "[get] .useRelativeDates" - case .p_useRelativeDates_set: return "[set] .useRelativeDates" - case .p_lastUsedSocialAuth_get: return "[get] .lastUsedSocialAuth" - case .p_lastUsedSocialAuth_set: return "[set] .lastUsedSocialAuth" - case .p_latestAvailableAppVersion_get: return "[get] .latestAvailableAppVersion" - case .p_latestAvailableAppVersion_set: return "[set] .latestAvailableAppVersion" - case .p_updateAppRequired_get: return "[get] .updateAppRequired" - case .p_updateAppRequired_set: return "[set] .updateAppRequired" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func accessToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_accessToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func refreshToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_refreshToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func pushToken(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_pushToken_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignFullName(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignFullName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func appleSignEmail(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_appleSignEmail_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func cookiesDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_cookiesDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func reviewLastShownVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_reviewLastShownVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastReviewDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_lastReviewDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func user(getter defaultValue: DataLayer.User?...) -> PropertyStub { - return Given(method: .p_user_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func userSettings(getter defaultValue: UserSettings?...) -> PropertyStub { - return Given(method: .p_userSettings_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func resetAppSupportDirectoryUserData(getter defaultValue: Bool?...) -> PropertyStub { - return Given(method: .p_resetAppSupportDirectoryUserData_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func useRelativeDates(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_useRelativeDates_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastUsedSocialAuth(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_lastUsedSocialAuth_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func latestAvailableAppVersion(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_latestAvailableAppVersion_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func updateAppRequired(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_updateAppRequired_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func clear() -> Verify { return Verify(method: .m_clear)} - public static var accessToken: Verify { return Verify(method: .p_accessToken_get) } - public static func accessToken(set newValue: Parameter) -> Verify { return Verify(method: .p_accessToken_set(newValue)) } - public static var refreshToken: Verify { return Verify(method: .p_refreshToken_get) } - public static func refreshToken(set newValue: Parameter) -> Verify { return Verify(method: .p_refreshToken_set(newValue)) } - public static var pushToken: Verify { return Verify(method: .p_pushToken_get) } - public static func pushToken(set newValue: Parameter) -> Verify { return Verify(method: .p_pushToken_set(newValue)) } - public static var appleSignFullName: Verify { return Verify(method: .p_appleSignFullName_get) } - public static func appleSignFullName(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignFullName_set(newValue)) } - public static var appleSignEmail: Verify { return Verify(method: .p_appleSignEmail_get) } - public static func appleSignEmail(set newValue: Parameter) -> Verify { return Verify(method: .p_appleSignEmail_set(newValue)) } - public static var cookiesDate: Verify { return Verify(method: .p_cookiesDate_get) } - public static func cookiesDate(set newValue: Parameter) -> Verify { return Verify(method: .p_cookiesDate_set(newValue)) } - public static var reviewLastShownVersion: Verify { return Verify(method: .p_reviewLastShownVersion_get) } - public static func reviewLastShownVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_reviewLastShownVersion_set(newValue)) } - public static var lastReviewDate: Verify { return Verify(method: .p_lastReviewDate_get) } - public static func lastReviewDate(set newValue: Parameter) -> Verify { return Verify(method: .p_lastReviewDate_set(newValue)) } - public static var user: Verify { return Verify(method: .p_user_get) } - public static func user(set newValue: Parameter) -> Verify { return Verify(method: .p_user_set(newValue)) } - public static var userSettings: Verify { return Verify(method: .p_userSettings_get) } - public static func userSettings(set newValue: Parameter) -> Verify { return Verify(method: .p_userSettings_set(newValue)) } - public static var resetAppSupportDirectoryUserData: Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_get) } - public static func resetAppSupportDirectoryUserData(set newValue: Parameter) -> Verify { return Verify(method: .p_resetAppSupportDirectoryUserData_set(newValue)) } - public static var useRelativeDates: Verify { return Verify(method: .p_useRelativeDates_get) } - public static func useRelativeDates(set newValue: Parameter) -> Verify { return Verify(method: .p_useRelativeDates_set(newValue)) } - public static var lastUsedSocialAuth: Verify { return Verify(method: .p_lastUsedSocialAuth_get) } - public static func lastUsedSocialAuth(set newValue: Parameter) -> Verify { return Verify(method: .p_lastUsedSocialAuth_set(newValue)) } - public static var latestAvailableAppVersion: Verify { return Verify(method: .p_latestAvailableAppVersion_get) } - public static func latestAvailableAppVersion(set newValue: Parameter) -> Verify { return Verify(method: .p_latestAvailableAppVersion_set(newValue)) } - public static var updateAppRequired: Verify { return Verify(method: .p_updateAppRequired_get) } - public static func updateAppRequired(set newValue: Parameter) -> Verify { return Verify(method: .p_updateAppRequired_set(newValue)) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func clear(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_clear, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - CourseStructureManagerProtocol - -open class CourseStructureManagerProtocolMock: CourseStructureManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func getLoadedCourseBlocks(courseID: String) throws -> CourseStructure { - addInvocation(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseStructure - do { - __value = try methodReturnValue(.m_getLoadedCourseBlocks__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - Failure("Stub return value not specified for getLoadedCourseBlocks(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - open func shiftDueDates(courseID: String) throws { - addInvocation(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - do { - _ = try methodReturnValue(.m_shiftDueDates__courseID_courseID(Parameter.value(`courseID`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - - fileprivate enum MethodType { - case m_getCourseBlocks__courseID_courseID(Parameter) - case m_getLoadedCourseBlocks__courseID_courseID(Parameter) - case m_shiftDueDates__courseID_courseID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseBlocks__courseID_courseID(let lhsCourseid), .m_getCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getLoadedCourseBlocks__courseID_courseID(let lhsCourseid), .m_getLoadedCourseBlocks__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_shiftDueDates__courseID_courseID(let lhsCourseid), .m_shiftDueDates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_getLoadedCourseBlocks__courseID_courseID(p0): return p0.intValue - case let .m_shiftDueDates__courseID_courseID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getCourseBlocks__courseID_courseID: return ".getCourseBlocks(courseID:)" - case .m_getLoadedCourseBlocks__courseID_courseID: return ".getLoadedCourseBlocks(courseID:)" - case .m_shiftDueDates__courseID_courseID: return ".shiftDueDates(courseID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willReturn: CourseStructure...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func getLoadedCourseBlocks(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getLoadedCourseBlocks(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseStructure).self) - willProduce(stubber) - return given - } - public static func shiftDueDates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func shiftDueDates(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_shiftDueDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseBlocks__courseID_courseID(`courseID`))} - public static func getLoadedCourseBlocks(courseID: Parameter) -> Verify { return Verify(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`))} - public static func shiftDueDates(courseID: Parameter) -> Verify { return Verify(method: .m_shiftDueDates__courseID_courseID(`courseID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func getLoadedCourseBlocks(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getLoadedCourseBlocks__courseID_courseID(`courseID`), performs: perform) - } - public static func shiftDueDates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_shiftDueDates__courseID_courseID(`courseID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - DownloadManagerProtocol - -open class DownloadManagerProtocolMock: DownloadManagerProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCurrentDownloadTask() -> DownloadDataTask? { - addInvocation(.m_getCurrentDownloadTask) - let perform = methodPerformValue(.m_getCurrentDownloadTask) as? () -> Void - perform?() - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_getCurrentDownloadTask).casted() - } catch { - // do nothing - } - return __value - } - - open func eventPublisher() -> AnyPublisher { - addInvocation(.m_eventPublisher) - let perform = methodPerformValue(.m_eventPublisher) as? () -> Void - perform?() - var __value: AnyPublisher - do { - __value = try methodReturnValue(.m_eventPublisher).casted() - } catch { - onFatalFailure("Stub return value not specified for eventPublisher(). Use given") - Failure("Stub return value not specified for eventPublisher(). Use given") - } - return __value - } - - open func addToDownloadQueue(blocks: [CourseBlock]) throws { - addInvocation(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - do { - _ = try methodReturnValue(.m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getDownloadTasks() -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasks) - let perform = methodPerformValue(.m_getDownloadTasks) as? () -> Void - perform?() - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasks).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasks(). Use given") - Failure("Stub return value not specified for getDownloadTasks(). Use given") - } - return __value - } - - open func getDownloadTasksForCourse(_ courseId: String) -> [DownloadDataTask] { - addInvocation(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [DownloadDataTask] - do { - __value = try methodReturnValue(.m_getDownloadTasksForCourse__courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - Failure("Stub return value not specified for getDownloadTasksForCourse(_ courseId: String). Use given") - } - return __value - } - - open func cancelDownloading(courseId: String, blocks: [CourseBlock]) throws { - addInvocation(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))) as? (String, [CourseBlock]) -> Void - perform?(`courseId`, `blocks`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter.value(`courseId`), Parameter<[CourseBlock]>.value(`blocks`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(task: DownloadDataTask) throws { - addInvocation(.m_cancelDownloading__task_task(Parameter.value(`task`))) - let perform = methodPerformValue(.m_cancelDownloading__task_task(Parameter.value(`task`))) as? (DownloadDataTask) -> Void - perform?(`task`) - do { - _ = try methodReturnValue(.m_cancelDownloading__task_task(Parameter.value(`task`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelDownloading(courseId: String) throws { - addInvocation(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - do { - _ = try methodReturnValue(.m_cancelDownloading__courseId_courseId(Parameter.value(`courseId`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func cancelAllDownloading() throws { - addInvocation(.m_cancelAllDownloading) - let perform = methodPerformValue(.m_cancelAllDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_cancelAllDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func deleteAll() { - addInvocation(.m_deleteAll) - let perform = methodPerformValue(.m_deleteAll) as? () -> Void - perform?() - } - - open func fileUrl(for blockId: String) -> URL? { - addInvocation(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: URL? = nil - do { - __value = try methodReturnValue(.m_fileUrl__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func resumeDownloading() throws { - addInvocation(.m_resumeDownloading) - let perform = methodPerformValue(.m_resumeDownloading) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_resumeDownloading).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func isLargeVideosSize(blocks: [CourseBlock]) -> Bool { - addInvocation(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) - let perform = methodPerformValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))) as? ([CourseBlock]) -> Void - perform?(`blocks`) - var __value: Bool - do { - __value = try methodReturnValue(.m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>.value(`blocks`))).casted() - } catch { - onFatalFailure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - Failure("Stub return value not specified for isLargeVideosSize(blocks: [CourseBlock]). Use given") - } - return __value - } - - open func removeAppSupportDirectoryUnusedContent() { - addInvocation(.m_removeAppSupportDirectoryUnusedContent) - let perform = methodPerformValue(.m_removeAppSupportDirectoryUnusedContent) as? () -> Void - perform?() - } - - open func delete(blocks: [CourseBlock], courseId: String) { - addInvocation(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>.value(`blocks`), Parameter.value(`courseId`))) as? ([CourseBlock], String) -> Void - perform?(`blocks`, `courseId`) - } - - open func downloadTask(for blockId: String) -> DownloadDataTask? { - addInvocation(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) - let perform = methodPerformValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))) as? (String) -> Void - perform?(`blockId`) - var __value: DownloadDataTask? = nil - do { - __value = try methodReturnValue(.m_downloadTask__for_blockId(Parameter.value(`blockId`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getFreeDiskSpace() -> Int? { - addInvocation(.m_getFreeDiskSpace) - let perform = methodPerformValue(.m_getFreeDiskSpace) as? () -> Void - perform?() - var __value: Int? = nil - do { - __value = try methodReturnValue(.m_getFreeDiskSpace).casted() - } catch { - // do nothing - } - return __value - } - - - fileprivate enum MethodType { - case m_getCurrentDownloadTask - case m_eventPublisher - case m_addToDownloadQueue__blocks_blocks(Parameter<[CourseBlock]>) - case m_getDownloadTasks - case m_getDownloadTasksForCourse__courseId(Parameter) - case m_cancelDownloading__courseId_courseIdblocks_blocks(Parameter, Parameter<[CourseBlock]>) - case m_cancelDownloading__task_task(Parameter) - case m_cancelDownloading__courseId_courseId(Parameter) - case m_cancelAllDownloading - case m_deleteAll - case m_fileUrl__for_blockId(Parameter) - case m_resumeDownloading - case m_isLargeVideosSize__blocks_blocks(Parameter<[CourseBlock]>) - case m_removeAppSupportDirectoryUnusedContent - case m_delete__blocks_blockscourseId_courseId(Parameter<[CourseBlock]>, Parameter) - case m_downloadTask__for_blockId(Parameter) - case m_getFreeDiskSpace - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCurrentDownloadTask, .m_getCurrentDownloadTask): return .match - - case (.m_eventPublisher, .m_eventPublisher): return .match - - case (.m_addToDownloadQueue__blocks_blocks(let lhsBlocks), .m_addToDownloadQueue__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_getDownloadTasks, .m_getDownloadTasks): return .match - - case (.m_getDownloadTasksForCourse__courseId(let lhsCourseid), .m_getDownloadTasksForCourse__courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "_ courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseIdblocks_blocks(let lhsCourseid, let lhsBlocks), .m_cancelDownloading__courseId_courseIdblocks_blocks(let rhsCourseid, let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__task_task(let lhsTask), .m_cancelDownloading__task_task(let rhsTask)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTask, rhs: rhsTask, with: matcher), lhsTask, rhsTask, "task")) - return Matcher.ComparisonResult(results) - - case (.m_cancelDownloading__courseId_courseId(let lhsCourseid), .m_cancelDownloading__courseId_courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_cancelAllDownloading, .m_cancelAllDownloading): return .match - - case (.m_deleteAll, .m_deleteAll): return .match - - case (.m_fileUrl__for_blockId(let lhsBlockid), .m_fileUrl__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_resumeDownloading, .m_resumeDownloading): return .match - - case (.m_isLargeVideosSize__blocks_blocks(let lhsBlocks), .m_isLargeVideosSize__blocks_blocks(let rhsBlocks)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - return Matcher.ComparisonResult(results) - - case (.m_removeAppSupportDirectoryUnusedContent, .m_removeAppSupportDirectoryUnusedContent): return .match - - case (.m_delete__blocks_blockscourseId_courseId(let lhsBlocks, let lhsCourseid), .m_delete__blocks_blockscourseId_courseId(let rhsBlocks, let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlocks, rhs: rhsBlocks, with: matcher), lhsBlocks, rhsBlocks, "blocks")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseId")) - return Matcher.ComparisonResult(results) - - case (.m_downloadTask__for_blockId(let lhsBlockid), .m_downloadTask__for_blockId(let rhsBlockid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "for blockId")) - return Matcher.ComparisonResult(results) - - case (.m_getFreeDiskSpace, .m_getFreeDiskSpace): return .match - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_getCurrentDownloadTask: return 0 - case .m_eventPublisher: return 0 - case let .m_addToDownloadQueue__blocks_blocks(p0): return p0.intValue - case .m_getDownloadTasks: return 0 - case let .m_getDownloadTasksForCourse__courseId(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseIdblocks_blocks(p0, p1): return p0.intValue + p1.intValue - case let .m_cancelDownloading__task_task(p0): return p0.intValue - case let .m_cancelDownloading__courseId_courseId(p0): return p0.intValue - case .m_cancelAllDownloading: return 0 - case .m_deleteAll: return 0 - case let .m_fileUrl__for_blockId(p0): return p0.intValue - case .m_resumeDownloading: return 0 - case let .m_isLargeVideosSize__blocks_blocks(p0): return p0.intValue - case .m_removeAppSupportDirectoryUnusedContent: return 0 - case let .m_delete__blocks_blockscourseId_courseId(p0, p1): return p0.intValue + p1.intValue - case let .m_downloadTask__for_blockId(p0): return p0.intValue - case .m_getFreeDiskSpace: return 0 - } - } - func assertionName() -> String { - switch self { - case .m_getCurrentDownloadTask: return ".getCurrentDownloadTask()" - case .m_eventPublisher: return ".eventPublisher()" - case .m_addToDownloadQueue__blocks_blocks: return ".addToDownloadQueue(blocks:)" - case .m_getDownloadTasks: return ".getDownloadTasks()" - case .m_getDownloadTasksForCourse__courseId: return ".getDownloadTasksForCourse(_:)" - case .m_cancelDownloading__courseId_courseIdblocks_blocks: return ".cancelDownloading(courseId:blocks:)" - case .m_cancelDownloading__task_task: return ".cancelDownloading(task:)" - case .m_cancelDownloading__courseId_courseId: return ".cancelDownloading(courseId:)" - case .m_cancelAllDownloading: return ".cancelAllDownloading()" - case .m_deleteAll: return ".deleteAll()" - case .m_fileUrl__for_blockId: return ".fileUrl(for:)" - case .m_resumeDownloading: return ".resumeDownloading()" - case .m_isLargeVideosSize__blocks_blocks: return ".isLargeVideosSize(blocks:)" - case .m_removeAppSupportDirectoryUnusedContent: return ".removeAppSupportDirectoryUnusedContent()" - case .m_delete__blocks_blockscourseId_courseId: return ".delete(blocks:courseId:)" - case .m_downloadTask__for_blockId: return ".downloadTask(for:)" - case .m_getFreeDiskSpace: return ".getFreeDiskSpace()" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCurrentDownloadTask(willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func eventPublisher(willReturn: AnyPublisher...) -> MethodStub { - return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasks(willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willReturn: [DownloadDataTask]...) -> MethodStub { - return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func fileUrl(for blockId: Parameter, willReturn: URL?...) -> MethodStub { - return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willReturn: Bool...) -> MethodStub { - return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func downloadTask(for blockId: Parameter, willReturn: DownloadDataTask?...) -> MethodStub { - return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getFreeDiskSpace(willReturn: Int?...) -> MethodStub { - return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCurrentDownloadTask(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_getCurrentDownloadTask, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func eventPublisher(willProduce: (Stubber>) -> Void) -> MethodStub { - let willReturn: [AnyPublisher] = [] - let given: Given = { return Given(method: .m_eventPublisher, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (AnyPublisher).self) - willProduce(stubber) - return given - } - public static func getDownloadTasks(willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasks, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, willProduce: (Stubber<[DownloadDataTask]>) -> Void) -> MethodStub { - let willReturn: [[DownloadDataTask]] = [] - let given: Given = { return Given(method: .m_getDownloadTasksForCourse__courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([DownloadDataTask]).self) - willProduce(stubber) - return given - } - public static func fileUrl(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [URL?] = [] - let given: Given = { return Given(method: .m_fileUrl__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (URL?).self) - willProduce(stubber) - return given - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Bool] = [] - let given: Given = { return Given(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Bool).self) - willProduce(stubber) - return given - } - public static func downloadTask(for blockId: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [DownloadDataTask?] = [] - let given: Given = { return Given(method: .m_downloadTask__for_blockId(`blockId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (DownloadDataTask?).self) - willProduce(stubber) - return given - } - public static func getFreeDiskSpace(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [Int?] = [] - let given: Given = { return Given(method: .m_getFreeDiskSpace, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (Int?).self) - willProduce(stubber) - return given - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(task: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(task: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__task_task(`task`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelDownloading(courseId: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelDownloading(courseId: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelDownloading__courseId_courseId(`courseId`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func cancelAllDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func cancelAllDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_cancelAllDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func resumeDownloading(willThrow: Error...) -> MethodStub { - return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func resumeDownloading(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_resumeDownloading, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCurrentDownloadTask() -> Verify { return Verify(method: .m_getCurrentDownloadTask)} - public static func eventPublisher() -> Verify { return Verify(method: .m_eventPublisher)} - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_addToDownloadQueue__blocks_blocks(`blocks`))} - public static func getDownloadTasks() -> Verify { return Verify(method: .m_getDownloadTasks)} - public static func getDownloadTasksForCourse(_ courseId: Parameter) -> Verify { return Verify(method: .m_getDownloadTasksForCourse__courseId(`courseId`))} - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`))} - public static func cancelDownloading(task: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__task_task(`task`))} - public static func cancelDownloading(courseId: Parameter) -> Verify { return Verify(method: .m_cancelDownloading__courseId_courseId(`courseId`))} - public static func cancelAllDownloading() -> Verify { return Verify(method: .m_cancelAllDownloading)} - public static func deleteAll() -> Verify { return Verify(method: .m_deleteAll)} - public static func fileUrl(for blockId: Parameter) -> Verify { return Verify(method: .m_fileUrl__for_blockId(`blockId`))} - public static func resumeDownloading() -> Verify { return Verify(method: .m_resumeDownloading)} - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>) -> Verify { return Verify(method: .m_isLargeVideosSize__blocks_blocks(`blocks`))} - public static func removeAppSupportDirectoryUnusedContent() -> Verify { return Verify(method: .m_removeAppSupportDirectoryUnusedContent)} - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter) -> Verify { return Verify(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`))} - public static func downloadTask(for blockId: Parameter) -> Verify { return Verify(method: .m_downloadTask__for_blockId(`blockId`))} - public static func getFreeDiskSpace() -> Verify { return Verify(method: .m_getFreeDiskSpace)} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCurrentDownloadTask(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getCurrentDownloadTask, performs: perform) - } - public static func eventPublisher(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_eventPublisher, performs: perform) - } - public static func addToDownloadQueue(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_addToDownloadQueue__blocks_blocks(`blocks`), performs: perform) - } - public static func getDownloadTasks(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getDownloadTasks, performs: perform) - } - public static func getDownloadTasksForCourse(_ courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getDownloadTasksForCourse__courseId(`courseId`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, blocks: Parameter<[CourseBlock]>, perform: @escaping (String, [CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseIdblocks_blocks(`courseId`, `blocks`), performs: perform) - } - public static func cancelDownloading(task: Parameter, perform: @escaping (DownloadDataTask) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__task_task(`task`), performs: perform) - } - public static func cancelDownloading(courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_cancelDownloading__courseId_courseId(`courseId`), performs: perform) - } - public static func cancelAllDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_cancelAllDownloading, performs: perform) - } - public static func deleteAll(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAll, performs: perform) - } - public static func fileUrl(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_fileUrl__for_blockId(`blockId`), performs: perform) - } - public static func resumeDownloading(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_resumeDownloading, performs: perform) - } - public static func isLargeVideosSize(blocks: Parameter<[CourseBlock]>, perform: @escaping ([CourseBlock]) -> Void) -> Perform { - return Perform(method: .m_isLargeVideosSize__blocks_blocks(`blocks`), performs: perform) - } - public static func removeAppSupportDirectoryUnusedContent(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeAppSupportDirectoryUnusedContent, performs: perform) - } - public static func delete(blocks: Parameter<[CourseBlock]>, courseId: Parameter, perform: @escaping ([CourseBlock], String) -> Void) -> Perform { - return Perform(method: .m_delete__blocks_blockscourseId_courseId(`blocks`, `courseId`), performs: perform) - } - public static func downloadTask(for blockId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_downloadTask__for_blockId(`blockId`), performs: perform) - } - public static func getFreeDiskSpace(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getFreeDiskSpace, performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - OfflineSyncInteractorProtocol - -open class OfflineSyncInteractorProtocolMock: OfflineSyncInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func submitOfflineProgress(courseID: String, blockID: String, data: String) throws -> Bool { - addInvocation(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) - let perform = methodPerformValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))) as? (String, String, String) -> Void - perform?(`courseID`, `blockID`, `data`) - var __value: Bool - do { - __value = try methodReturnValue(.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter.value(`courseID`), Parameter.value(`blockID`), Parameter.value(`data`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - Failure("Stub return value not specified for submitOfflineProgress(courseID: String, blockID: String, data: String). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(Parameter, Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let lhsCourseid, let lhsBlockid, let lhsData), .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(let rhsCourseid, let rhsBlockid, let rhsData)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBlockid, rhs: rhsBlockid, with: matcher), lhsBlockid, rhsBlockid, "blockID")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsData, rhs: rhsData, with: matcher), lhsData, rhsData, "data")) - return Matcher.ComparisonResult(results) - } - } - - func intValue() -> Int { - switch self { - case let .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data: return ".submitOfflineProgress(courseID:blockID:data:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Bool).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter) -> Verify { return Verify(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func submitOfflineProgress(courseID: Parameter, blockID: Parameter, data: Parameter, perform: @escaping (String, String, String) -> Void) -> Perform { - return Perform(method: .m_submitOfflineProgress__courseID_courseIDblockID_blockIDdata_data(`courseID`, `blockID`, `data`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ProfileAnalytics - -open class ProfileAnalyticsMock: ProfileAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func profileEditClicked() { - addInvocation(.m_profileEditClicked) - let perform = methodPerformValue(.m_profileEditClicked) as? () -> Void - perform?() - } - - open func profileSwitch(action: String) { - addInvocation(.m_profileSwitch__action_action(Parameter.value(`action`))) - let perform = methodPerformValue(.m_profileSwitch__action_action(Parameter.value(`action`))) as? (String) -> Void - perform?(`action`) - } - - open func profileEditDoneClicked() { - addInvocation(.m_profileEditDoneClicked) - let perform = methodPerformValue(.m_profileEditDoneClicked) as? () -> Void - perform?() - } - - open func profileDeleteAccountClicked() { - addInvocation(.m_profileDeleteAccountClicked) - let perform = methodPerformValue(.m_profileDeleteAccountClicked) as? () -> Void - perform?() - } - - open func profileVideoSettingsClicked() { - addInvocation(.m_profileVideoSettingsClicked) - let perform = methodPerformValue(.m_profileVideoSettingsClicked) as? () -> Void - perform?() - } - - open func privacyPolicyClicked() { - addInvocation(.m_privacyPolicyClicked) - let perform = methodPerformValue(.m_privacyPolicyClicked) as? () -> Void - perform?() - } - - open func cookiePolicyClicked() { - addInvocation(.m_cookiePolicyClicked) - let perform = methodPerformValue(.m_cookiePolicyClicked) as? () -> Void - perform?() - } - - open func emailSupportClicked() { - addInvocation(.m_emailSupportClicked) - let perform = methodPerformValue(.m_emailSupportClicked) as? () -> Void - perform?() - } - - open func faqClicked() { - addInvocation(.m_faqClicked) - let perform = methodPerformValue(.m_faqClicked) as? () -> Void - perform?() - } - - open func tosClicked() { - addInvocation(.m_tosClicked) - let perform = methodPerformValue(.m_tosClicked) as? () -> Void - perform?() - } - - open func dataSellClicked() { - addInvocation(.m_dataSellClicked) - let perform = methodPerformValue(.m_dataSellClicked) as? () -> Void - perform?() - } - - open func userLogout(force: Bool) { - addInvocation(.m_userLogout__force_force(Parameter.value(`force`))) - let perform = methodPerformValue(.m_userLogout__force_force(Parameter.value(`force`))) as? (Bool) -> Void - perform?(`force`) - } - - open func profileWifiToggle(action: String) { - addInvocation(.m_profileWifiToggle__action_action(Parameter.value(`action`))) - let perform = methodPerformValue(.m_profileWifiToggle__action_action(Parameter.value(`action`))) as? (String) -> Void - perform?(`action`) - } - - open func profileUserDeleteAccountClicked() { - addInvocation(.m_profileUserDeleteAccountClicked) - let perform = methodPerformValue(.m_profileUserDeleteAccountClicked) as? () -> Void - perform?() - } - - open func profileDeleteAccountSuccess(success: Bool) { - addInvocation(.m_profileDeleteAccountSuccess__success_success(Parameter.value(`success`))) - let perform = methodPerformValue(.m_profileDeleteAccountSuccess__success_success(Parameter.value(`success`))) as? (Bool) -> Void - perform?(`success`) - } - - open func profileTrackEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_profileTrackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_profileTrackEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - open func profileScreenEvent(_ event: AnalyticsEvent, biValue: EventBIValue) { - addInvocation(.m_profileScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) - let perform = methodPerformValue(.m_profileScreenEvent__eventbiValue_biValue(Parameter.value(`event`), Parameter.value(`biValue`))) as? (AnalyticsEvent, EventBIValue) -> Void - perform?(`event`, `biValue`) - } - - - fileprivate enum MethodType { - case m_profileEditClicked - case m_profileSwitch__action_action(Parameter) - case m_profileEditDoneClicked - case m_profileDeleteAccountClicked - case m_profileVideoSettingsClicked - case m_privacyPolicyClicked - case m_cookiePolicyClicked - case m_emailSupportClicked - case m_faqClicked - case m_tosClicked - case m_dataSellClicked - case m_userLogout__force_force(Parameter) - case m_profileWifiToggle__action_action(Parameter) - case m_profileUserDeleteAccountClicked - case m_profileDeleteAccountSuccess__success_success(Parameter) - case m_profileTrackEvent__eventbiValue_biValue(Parameter, Parameter) - case m_profileScreenEvent__eventbiValue_biValue(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_profileEditClicked, .m_profileEditClicked): return .match - - case (.m_profileSwitch__action_action(let lhsAction), .m_profileSwitch__action_action(let rhsAction)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - return Matcher.ComparisonResult(results) - - case (.m_profileEditDoneClicked, .m_profileEditDoneClicked): return .match - - case (.m_profileDeleteAccountClicked, .m_profileDeleteAccountClicked): return .match - - case (.m_profileVideoSettingsClicked, .m_profileVideoSettingsClicked): return .match - - case (.m_privacyPolicyClicked, .m_privacyPolicyClicked): return .match - - case (.m_cookiePolicyClicked, .m_cookiePolicyClicked): return .match - - case (.m_emailSupportClicked, .m_emailSupportClicked): return .match - - case (.m_faqClicked, .m_faqClicked): return .match - - case (.m_tosClicked, .m_tosClicked): return .match - - case (.m_dataSellClicked, .m_dataSellClicked): return .match - - case (.m_userLogout__force_force(let lhsForce), .m_userLogout__force_force(let rhsForce)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsForce, rhs: rhsForce, with: matcher), lhsForce, rhsForce, "force")) - return Matcher.ComparisonResult(results) - - case (.m_profileWifiToggle__action_action(let lhsAction), .m_profileWifiToggle__action_action(let rhsAction)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - return Matcher.ComparisonResult(results) - - case (.m_profileUserDeleteAccountClicked, .m_profileUserDeleteAccountClicked): return .match - - case (.m_profileDeleteAccountSuccess__success_success(let lhsSuccess), .m_profileDeleteAccountSuccess__success_success(let rhsSuccess)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSuccess, rhs: rhsSuccess, with: matcher), lhsSuccess, rhsSuccess, "success")) - return Matcher.ComparisonResult(results) - - case (.m_profileTrackEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_profileTrackEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - - case (.m_profileScreenEvent__eventbiValue_biValue(let lhsEvent, let lhsBivalue), .m_profileScreenEvent__eventbiValue_biValue(let rhsEvent, let rhsBivalue)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsBivalue, rhs: rhsBivalue, with: matcher), lhsBivalue, rhsBivalue, "biValue")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_profileEditClicked: return 0 - case let .m_profileSwitch__action_action(p0): return p0.intValue - case .m_profileEditDoneClicked: return 0 - case .m_profileDeleteAccountClicked: return 0 - case .m_profileVideoSettingsClicked: return 0 - case .m_privacyPolicyClicked: return 0 - case .m_cookiePolicyClicked: return 0 - case .m_emailSupportClicked: return 0 - case .m_faqClicked: return 0 - case .m_tosClicked: return 0 - case .m_dataSellClicked: return 0 - case let .m_userLogout__force_force(p0): return p0.intValue - case let .m_profileWifiToggle__action_action(p0): return p0.intValue - case .m_profileUserDeleteAccountClicked: return 0 - case let .m_profileDeleteAccountSuccess__success_success(p0): return p0.intValue - case let .m_profileTrackEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - case let .m_profileScreenEvent__eventbiValue_biValue(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_profileEditClicked: return ".profileEditClicked()" - case .m_profileSwitch__action_action: return ".profileSwitch(action:)" - case .m_profileEditDoneClicked: return ".profileEditDoneClicked()" - case .m_profileDeleteAccountClicked: return ".profileDeleteAccountClicked()" - case .m_profileVideoSettingsClicked: return ".profileVideoSettingsClicked()" - case .m_privacyPolicyClicked: return ".privacyPolicyClicked()" - case .m_cookiePolicyClicked: return ".cookiePolicyClicked()" - case .m_emailSupportClicked: return ".emailSupportClicked()" - case .m_faqClicked: return ".faqClicked()" - case .m_tosClicked: return ".tosClicked()" - case .m_dataSellClicked: return ".dataSellClicked()" - case .m_userLogout__force_force: return ".userLogout(force:)" - case .m_profileWifiToggle__action_action: return ".profileWifiToggle(action:)" - case .m_profileUserDeleteAccountClicked: return ".profileUserDeleteAccountClicked()" - case .m_profileDeleteAccountSuccess__success_success: return ".profileDeleteAccountSuccess(success:)" - case .m_profileTrackEvent__eventbiValue_biValue: return ".profileTrackEvent(_:biValue:)" - case .m_profileScreenEvent__eventbiValue_biValue: return ".profileScreenEvent(_:biValue:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func profileEditClicked() -> Verify { return Verify(method: .m_profileEditClicked)} - public static func profileSwitch(action: Parameter) -> Verify { return Verify(method: .m_profileSwitch__action_action(`action`))} - public static func profileEditDoneClicked() -> Verify { return Verify(method: .m_profileEditDoneClicked)} - public static func profileDeleteAccountClicked() -> Verify { return Verify(method: .m_profileDeleteAccountClicked)} - public static func profileVideoSettingsClicked() -> Verify { return Verify(method: .m_profileVideoSettingsClicked)} - public static func privacyPolicyClicked() -> Verify { return Verify(method: .m_privacyPolicyClicked)} - public static func cookiePolicyClicked() -> Verify { return Verify(method: .m_cookiePolicyClicked)} - public static func emailSupportClicked() -> Verify { return Verify(method: .m_emailSupportClicked)} - public static func faqClicked() -> Verify { return Verify(method: .m_faqClicked)} - public static func tosClicked() -> Verify { return Verify(method: .m_tosClicked)} - public static func dataSellClicked() -> Verify { return Verify(method: .m_dataSellClicked)} - public static func userLogout(force: Parameter) -> Verify { return Verify(method: .m_userLogout__force_force(`force`))} - public static func profileWifiToggle(action: Parameter) -> Verify { return Verify(method: .m_profileWifiToggle__action_action(`action`))} - public static func profileUserDeleteAccountClicked() -> Verify { return Verify(method: .m_profileUserDeleteAccountClicked)} - public static func profileDeleteAccountSuccess(success: Parameter) -> Verify { return Verify(method: .m_profileDeleteAccountSuccess__success_success(`success`))} - public static func profileTrackEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_profileTrackEvent__eventbiValue_biValue(`event`, `biValue`))} - public static func profileScreenEvent(_ event: Parameter, biValue: Parameter) -> Verify { return Verify(method: .m_profileScreenEvent__eventbiValue_biValue(`event`, `biValue`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func profileEditClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_profileEditClicked, performs: perform) - } - public static func profileSwitch(action: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_profileSwitch__action_action(`action`), performs: perform) - } - public static func profileEditDoneClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_profileEditDoneClicked, performs: perform) - } - public static func profileDeleteAccountClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_profileDeleteAccountClicked, performs: perform) - } - public static func profileVideoSettingsClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_profileVideoSettingsClicked, performs: perform) - } - public static func privacyPolicyClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_privacyPolicyClicked, performs: perform) - } - public static func cookiePolicyClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_cookiePolicyClicked, performs: perform) - } - public static func emailSupportClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_emailSupportClicked, performs: perform) - } - public static func faqClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_faqClicked, performs: perform) - } - public static func tosClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_tosClicked, performs: perform) - } - public static func dataSellClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_dataSellClicked, performs: perform) - } - public static func userLogout(force: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_userLogout__force_force(`force`), performs: perform) - } - public static func profileWifiToggle(action: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_profileWifiToggle__action_action(`action`), performs: perform) - } - public static func profileUserDeleteAccountClicked(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_profileUserDeleteAccountClicked, performs: perform) - } - public static func profileDeleteAccountSuccess(success: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_profileDeleteAccountSuccess__success_success(`success`), performs: perform) - } - public static func profileTrackEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_profileTrackEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - public static func profileScreenEvent(_ event: Parameter, biValue: Parameter, perform: @escaping (AnalyticsEvent, EventBIValue) -> Void) -> Perform { - return Perform(method: .m_profileScreenEvent__eventbiValue_biValue(`event`, `biValue`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ProfileInteractorProtocol - -open class ProfileInteractorProtocolMock: ProfileInteractorProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getUserProfile(username: String) throws -> UserProfile { - addInvocation(.m_getUserProfile__username_username(Parameter.value(`username`))) - let perform = methodPerformValue(.m_getUserProfile__username_username(Parameter.value(`username`))) as? (String) -> Void - perform?(`username`) - var __value: UserProfile - do { - __value = try methodReturnValue(.m_getUserProfile__username_username(Parameter.value(`username`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getUserProfile(username: String). Use given") - Failure("Stub return value not specified for getUserProfile(username: String). Use given") - } catch { - throw error - } - return __value - } - - open func getMyProfile() throws -> UserProfile { - addInvocation(.m_getMyProfile) - let perform = methodPerformValue(.m_getMyProfile) as? () -> Void - perform?() - var __value: UserProfile - do { - __value = try methodReturnValue(.m_getMyProfile).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getMyProfile(). Use given") - Failure("Stub return value not specified for getMyProfile(). Use given") - } catch { - throw error - } - return __value - } - - open func getMyProfileOffline() -> UserProfile? { - addInvocation(.m_getMyProfileOffline) - let perform = methodPerformValue(.m_getMyProfileOffline) as? () -> Void - perform?() - var __value: UserProfile? = nil - do { - __value = try methodReturnValue(.m_getMyProfileOffline).casted() - } catch { - // do nothing - } - return __value - } - - open func logOut() throws { - addInvocation(.m_logOut) - let perform = methodPerformValue(.m_logOut) as? () -> Void - perform?() - do { - _ = try methodReturnValue(.m_logOut).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func getSpokenLanguages() -> [PickerFields.Option] { - addInvocation(.m_getSpokenLanguages) - let perform = methodPerformValue(.m_getSpokenLanguages) as? () -> Void - perform?() - var __value: [PickerFields.Option] - do { - __value = try methodReturnValue(.m_getSpokenLanguages).casted() - } catch { - onFatalFailure("Stub return value not specified for getSpokenLanguages(). Use given") - Failure("Stub return value not specified for getSpokenLanguages(). Use given") - } - return __value - } - - open func getCountries() -> [PickerFields.Option] { - addInvocation(.m_getCountries) - let perform = methodPerformValue(.m_getCountries) as? () -> Void - perform?() - var __value: [PickerFields.Option] - do { - __value = try methodReturnValue(.m_getCountries).casted() - } catch { - onFatalFailure("Stub return value not specified for getCountries(). Use given") - Failure("Stub return value not specified for getCountries(). Use given") - } - return __value - } - - open func uploadProfilePicture(pictureData: Data) throws { - addInvocation(.m_uploadProfilePicture__pictureData_pictureData(Parameter.value(`pictureData`))) - let perform = methodPerformValue(.m_uploadProfilePicture__pictureData_pictureData(Parameter.value(`pictureData`))) as? (Data) -> Void - perform?(`pictureData`) - do { - _ = try methodReturnValue(.m_uploadProfilePicture__pictureData_pictureData(Parameter.value(`pictureData`))).casted() as Void - } catch MockError.notStubed { - // do nothing - } catch { - throw error - } - } - - open func deleteProfilePicture() throws -> Bool { - addInvocation(.m_deleteProfilePicture) - let perform = methodPerformValue(.m_deleteProfilePicture) as? () -> Void - perform?() - var __value: Bool - do { - __value = try methodReturnValue(.m_deleteProfilePicture).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for deleteProfilePicture(). Use given") - Failure("Stub return value not specified for deleteProfilePicture(). Use given") - } catch { - throw error - } - return __value - } - - open func updateUserProfile(parameters: [String: any Any & Sendable]) throws -> UserProfile { - addInvocation(.m_updateUserProfile__parameters_parameters(Parameter<[String: any Any & Sendable]>.value(`parameters`))) - let perform = methodPerformValue(.m_updateUserProfile__parameters_parameters(Parameter<[String: any Any & Sendable]>.value(`parameters`))) as? ([String: any Any & Sendable]) -> Void - perform?(`parameters`) - var __value: UserProfile - do { - __value = try methodReturnValue(.m_updateUserProfile__parameters_parameters(Parameter<[String: any Any & Sendable]>.value(`parameters`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for updateUserProfile(parameters: [String: any Any & Sendable]). Use given") - Failure("Stub return value not specified for updateUserProfile(parameters: [String: any Any & Sendable]). Use given") - } catch { - throw error - } - return __value - } - - open func deleteAccount(password: String) throws -> Bool { - addInvocation(.m_deleteAccount__password_password(Parameter.value(`password`))) - let perform = methodPerformValue(.m_deleteAccount__password_password(Parameter.value(`password`))) as? (String) -> Void - perform?(`password`) - var __value: Bool - do { - __value = try methodReturnValue(.m_deleteAccount__password_password(Parameter.value(`password`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for deleteAccount(password: String). Use given") - Failure("Stub return value not specified for deleteAccount(password: String). Use given") - } catch { - throw error - } - return __value - } - - open func getSettings() -> UserSettings { - addInvocation(.m_getSettings) - let perform = methodPerformValue(.m_getSettings) as? () -> Void - perform?() - var __value: UserSettings - do { - __value = try methodReturnValue(.m_getSettings).casted() - } catch { - onFatalFailure("Stub return value not specified for getSettings(). Use given") - Failure("Stub return value not specified for getSettings(). Use given") - } - return __value - } - - open func saveSettings(_ settings: UserSettings) { - addInvocation(.m_saveSettings__settings(Parameter.value(`settings`))) - let perform = methodPerformValue(.m_saveSettings__settings(Parameter.value(`settings`))) as? (UserSettings) -> Void - perform?(`settings`) - } - - open func enrollmentsStatus() throws -> [CourseForSync] { - addInvocation(.m_enrollmentsStatus) - let perform = methodPerformValue(.m_enrollmentsStatus) as? () -> Void - perform?() - var __value: [CourseForSync] - do { - __value = try methodReturnValue(.m_enrollmentsStatus).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for enrollmentsStatus(). Use given") - Failure("Stub return value not specified for enrollmentsStatus(). Use given") - } catch { - throw error - } - return __value - } - - open func getCourseDates(courseID: String) throws -> CourseDates { - addInvocation(.m_getCourseDates__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseDates__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseDates - do { - __value = try methodReturnValue(.m_getCourseDates__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch MockError.notStubed { - onFatalFailure("Stub return value not specified for getCourseDates(courseID: String). Use given") - Failure("Stub return value not specified for getCourseDates(courseID: String). Use given") - } catch { - throw error - } - return __value - } - - - fileprivate enum MethodType { - case m_getUserProfile__username_username(Parameter) - case m_getMyProfile - case m_getMyProfileOffline - case m_logOut - case m_getSpokenLanguages - case m_getCountries - case m_uploadProfilePicture__pictureData_pictureData(Parameter) - case m_deleteProfilePicture - case m_updateUserProfile__parameters_parameters(Parameter<[String: any Any & Sendable]>) - case m_deleteAccount__password_password(Parameter) - case m_getSettings - case m_saveSettings__settings(Parameter) - case m_enrollmentsStatus - case m_getCourseDates__courseID_courseID(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getUserProfile__username_username(let lhsUsername), .m_getUserProfile__username_username(let rhsUsername)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsername, rhs: rhsUsername, with: matcher), lhsUsername, rhsUsername, "username")) - return Matcher.ComparisonResult(results) - - case (.m_getMyProfile, .m_getMyProfile): return .match - - case (.m_getMyProfileOffline, .m_getMyProfileOffline): return .match - - case (.m_logOut, .m_logOut): return .match - - case (.m_getSpokenLanguages, .m_getSpokenLanguages): return .match - - case (.m_getCountries, .m_getCountries): return .match - - case (.m_uploadProfilePicture__pictureData_pictureData(let lhsPicturedata), .m_uploadProfilePicture__pictureData_pictureData(let rhsPicturedata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPicturedata, rhs: rhsPicturedata, with: matcher), lhsPicturedata, rhsPicturedata, "pictureData")) - return Matcher.ComparisonResult(results) - - case (.m_deleteProfilePicture, .m_deleteProfilePicture): return .match - - case (.m_updateUserProfile__parameters_parameters(let lhsParameters), .m_updateUserProfile__parameters_parameters(let rhsParameters)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsParameters, rhs: rhsParameters, with: matcher), lhsParameters, rhsParameters, "parameters")) - return Matcher.ComparisonResult(results) - - case (.m_deleteAccount__password_password(let lhsPassword), .m_deleteAccount__password_password(let rhsPassword)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPassword, rhs: rhsPassword, with: matcher), lhsPassword, rhsPassword, "password")) - return Matcher.ComparisonResult(results) - - case (.m_getSettings, .m_getSettings): return .match - - case (.m_saveSettings__settings(let lhsSettings), .m_saveSettings__settings(let rhsSettings)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSettings, rhs: rhsSettings, with: matcher), lhsSettings, rhsSettings, "_ settings")) - return Matcher.ComparisonResult(results) - - case (.m_enrollmentsStatus, .m_enrollmentsStatus): return .match - - case (.m_getCourseDates__courseID_courseID(let lhsCourseid), .m_getCourseDates__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getUserProfile__username_username(p0): return p0.intValue - case .m_getMyProfile: return 0 - case .m_getMyProfileOffline: return 0 - case .m_logOut: return 0 - case .m_getSpokenLanguages: return 0 - case .m_getCountries: return 0 - case let .m_uploadProfilePicture__pictureData_pictureData(p0): return p0.intValue - case .m_deleteProfilePicture: return 0 - case let .m_updateUserProfile__parameters_parameters(p0): return p0.intValue - case let .m_deleteAccount__password_password(p0): return p0.intValue - case .m_getSettings: return 0 - case let .m_saveSettings__settings(p0): return p0.intValue - case .m_enrollmentsStatus: return 0 - case let .m_getCourseDates__courseID_courseID(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getUserProfile__username_username: return ".getUserProfile(username:)" - case .m_getMyProfile: return ".getMyProfile()" - case .m_getMyProfileOffline: return ".getMyProfileOffline()" - case .m_logOut: return ".logOut()" - case .m_getSpokenLanguages: return ".getSpokenLanguages()" - case .m_getCountries: return ".getCountries()" - case .m_uploadProfilePicture__pictureData_pictureData: return ".uploadProfilePicture(pictureData:)" - case .m_deleteProfilePicture: return ".deleteProfilePicture()" - case .m_updateUserProfile__parameters_parameters: return ".updateUserProfile(parameters:)" - case .m_deleteAccount__password_password: return ".deleteAccount(password:)" - case .m_getSettings: return ".getSettings()" - case .m_saveSettings__settings: return ".saveSettings(_:)" - case .m_enrollmentsStatus: return ".enrollmentsStatus()" - case .m_getCourseDates__courseID_courseID: return ".getCourseDates(courseID:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getUserProfile(username: Parameter, willReturn: UserProfile...) -> MethodStub { - return Given(method: .m_getUserProfile__username_username(`username`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getMyProfile(willReturn: UserProfile...) -> MethodStub { - return Given(method: .m_getMyProfile, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getMyProfileOffline(willReturn: UserProfile?...) -> MethodStub { - return Given(method: .m_getMyProfileOffline, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getSpokenLanguages(willReturn: [PickerFields.Option]...) -> MethodStub { - return Given(method: .m_getSpokenLanguages, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCountries(willReturn: [PickerFields.Option]...) -> MethodStub { - return Given(method: .m_getCountries, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func deleteProfilePicture(willReturn: Bool...) -> MethodStub { - return Given(method: .m_deleteProfilePicture, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func updateUserProfile(parameters: Parameter<[String: any Any & Sendable]>, willReturn: UserProfile...) -> MethodStub { - return Given(method: .m_updateUserProfile__parameters_parameters(`parameters`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func deleteAccount(password: Parameter, willReturn: Bool...) -> MethodStub { - return Given(method: .m_deleteAccount__password_password(`password`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getSettings(willReturn: UserSettings...) -> MethodStub { - return Given(method: .m_getSettings, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func enrollmentsStatus(willReturn: [CourseForSync]...) -> MethodStub { - return Given(method: .m_enrollmentsStatus, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseDates(courseID: Parameter, willReturn: CourseDates...) -> MethodStub { - return Given(method: .m_getCourseDates__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getMyProfileOffline(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [UserProfile?] = [] - let given: Given = { return Given(method: .m_getMyProfileOffline, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (UserProfile?).self) - willProduce(stubber) - return given - } - public static func getSpokenLanguages(willProduce: (Stubber<[PickerFields.Option]>) -> Void) -> MethodStub { - let willReturn: [[PickerFields.Option]] = [] - let given: Given = { return Given(method: .m_getSpokenLanguages, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([PickerFields.Option]).self) - willProduce(stubber) - return given - } - public static func getCountries(willProduce: (Stubber<[PickerFields.Option]>) -> Void) -> MethodStub { - let willReturn: [[PickerFields.Option]] = [] - let given: Given = { return Given(method: .m_getCountries, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([PickerFields.Option]).self) - willProduce(stubber) - return given - } - public static func getSettings(willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [UserSettings] = [] - let given: Given = { return Given(method: .m_getSettings, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (UserSettings).self) - willProduce(stubber) - return given - } - public static func getUserProfile(username: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getUserProfile__username_username(`username`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getUserProfile(username: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getUserProfile__username_username(`username`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (UserProfile).self) - willProduce(stubber) - return given - } - public static func getMyProfile(willThrow: Error...) -> MethodStub { - return Given(method: .m_getMyProfile, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getMyProfile(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getMyProfile, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (UserProfile).self) - willProduce(stubber) - return given - } - public static func logOut(willThrow: Error...) -> MethodStub { - return Given(method: .m_logOut, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func logOut(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_logOut, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func uploadProfilePicture(pictureData: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_uploadProfilePicture__pictureData_pictureData(`pictureData`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func uploadProfilePicture(pictureData: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_uploadProfilePicture__pictureData_pictureData(`pictureData`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Void).self) - willProduce(stubber) - return given - } - public static func deleteProfilePicture(willThrow: Error...) -> MethodStub { - return Given(method: .m_deleteProfilePicture, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func deleteProfilePicture(willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_deleteProfilePicture, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Bool).self) - willProduce(stubber) - return given - } - public static func updateUserProfile(parameters: Parameter<[String: any Any & Sendable]>, willThrow: Error...) -> MethodStub { - return Given(method: .m_updateUserProfile__parameters_parameters(`parameters`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func updateUserProfile(parameters: Parameter<[String: any Any & Sendable]>, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_updateUserProfile__parameters_parameters(`parameters`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (UserProfile).self) - willProduce(stubber) - return given - } - public static func deleteAccount(password: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_deleteAccount__password_password(`password`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func deleteAccount(password: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_deleteAccount__password_password(`password`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (Bool).self) - willProduce(stubber) - return given - } - public static func enrollmentsStatus(willThrow: Error...) -> MethodStub { - return Given(method: .m_enrollmentsStatus, products: willThrow.map({ StubProduct.throw($0) })) - } - public static func enrollmentsStatus(willProduce: (StubberThrows<[CourseForSync]>) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_enrollmentsStatus, products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: ([CourseForSync]).self) - willProduce(stubber) - return given - } - public static func getCourseDates(courseID: Parameter, willThrow: Error...) -> MethodStub { - return Given(method: .m_getCourseDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) - } - public static func getCourseDates(courseID: Parameter, willProduce: (StubberThrows) -> Void) -> MethodStub { - let willThrow: [Error] = [] - let given: Given = { return Given(method: .m_getCourseDates__courseID_courseID(`courseID`), products: willThrow.map({ StubProduct.throw($0) })) }() - let stubber = given.stubThrows(for: (CourseDates).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getUserProfile(username: Parameter) -> Verify { return Verify(method: .m_getUserProfile__username_username(`username`))} - public static func getMyProfile() -> Verify { return Verify(method: .m_getMyProfile)} - public static func getMyProfileOffline() -> Verify { return Verify(method: .m_getMyProfileOffline)} - public static func logOut() -> Verify { return Verify(method: .m_logOut)} - public static func getSpokenLanguages() -> Verify { return Verify(method: .m_getSpokenLanguages)} - public static func getCountries() -> Verify { return Verify(method: .m_getCountries)} - public static func uploadProfilePicture(pictureData: Parameter) -> Verify { return Verify(method: .m_uploadProfilePicture__pictureData_pictureData(`pictureData`))} - public static func deleteProfilePicture() -> Verify { return Verify(method: .m_deleteProfilePicture)} - public static func updateUserProfile(parameters: Parameter<[String: any Any & Sendable]>) -> Verify { return Verify(method: .m_updateUserProfile__parameters_parameters(`parameters`))} - public static func deleteAccount(password: Parameter) -> Verify { return Verify(method: .m_deleteAccount__password_password(`password`))} - public static func getSettings() -> Verify { return Verify(method: .m_getSettings)} - public static func saveSettings(_ settings: Parameter) -> Verify { return Verify(method: .m_saveSettings__settings(`settings`))} - public static func enrollmentsStatus() -> Verify { return Verify(method: .m_enrollmentsStatus)} - public static func getCourseDates(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseDates__courseID_courseID(`courseID`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getUserProfile(username: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getUserProfile__username_username(`username`), performs: perform) - } - public static func getMyProfile(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getMyProfile, performs: perform) - } - public static func getMyProfileOffline(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getMyProfileOffline, performs: perform) - } - public static func logOut(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_logOut, performs: perform) - } - public static func getSpokenLanguages(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getSpokenLanguages, performs: perform) - } - public static func getCountries(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getCountries, performs: perform) - } - public static func uploadProfilePicture(pictureData: Parameter, perform: @escaping (Data) -> Void) -> Perform { - return Perform(method: .m_uploadProfilePicture__pictureData_pictureData(`pictureData`), performs: perform) - } - public static func deleteProfilePicture(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteProfilePicture, performs: perform) - } - public static func updateUserProfile(parameters: Parameter<[String: any Any & Sendable]>, perform: @escaping ([String: any Any & Sendable]) -> Void) -> Perform { - return Perform(method: .m_updateUserProfile__parameters_parameters(`parameters`), performs: perform) - } - public static func deleteAccount(password: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_deleteAccount__password_password(`password`), performs: perform) - } - public static func getSettings(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getSettings, performs: perform) - } - public static func saveSettings(_ settings: Parameter, perform: @escaping (UserSettings) -> Void) -> Perform { - return Perform(method: .m_saveSettings__settings(`settings`), performs: perform) - } - public static func enrollmentsStatus(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_enrollmentsStatus, performs: perform) - } - public static func getCourseDates(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseDates__courseID_courseID(`courseID`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ProfilePersistenceProtocol - -open class ProfilePersistenceProtocolMock: ProfilePersistenceProtocol, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func getCourseState(courseID: String) -> CourseCalendarState? { - addInvocation(.m_getCourseState__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_getCourseState__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - var __value: CourseCalendarState? = nil - do { - __value = try methodReturnValue(.m_getCourseState__courseID_courseID(Parameter.value(`courseID`))).casted() - } catch { - // do nothing - } - return __value - } - - open func getAllCourseStates() -> [CourseCalendarState] { - addInvocation(.m_getAllCourseStates) - let perform = methodPerformValue(.m_getAllCourseStates) as? () -> Void - perform?() - var __value: [CourseCalendarState] - do { - __value = try methodReturnValue(.m_getAllCourseStates).casted() - } catch { - onFatalFailure("Stub return value not specified for getAllCourseStates(). Use given") - Failure("Stub return value not specified for getAllCourseStates(). Use given") - } - return __value - } - - open func saveCourseState(state: CourseCalendarState) { - addInvocation(.m_saveCourseState__state_state(Parameter.value(`state`))) - let perform = methodPerformValue(.m_saveCourseState__state_state(Parameter.value(`state`))) as? (CourseCalendarState) -> Void - perform?(`state`) - } - - open func removeCourseState(courseID: String) { - addInvocation(.m_removeCourseState__courseID_courseID(Parameter.value(`courseID`))) - let perform = methodPerformValue(.m_removeCourseState__courseID_courseID(Parameter.value(`courseID`))) as? (String) -> Void - perform?(`courseID`) - } - - open func deleteAllCourseStatesAndEvents() { - addInvocation(.m_deleteAllCourseStatesAndEvents) - let perform = methodPerformValue(.m_deleteAllCourseStatesAndEvents) as? () -> Void - perform?() - } - - open func saveCourseCalendarEvent(_ event: CourseCalendarEvent) { - addInvocation(.m_saveCourseCalendarEvent__event(Parameter.value(`event`))) - let perform = methodPerformValue(.m_saveCourseCalendarEvent__event(Parameter.value(`event`))) as? (CourseCalendarEvent) -> Void - perform?(`event`) - } - - open func removeCourseCalendarEvents(for courseId: String) { - addInvocation(.m_removeCourseCalendarEvents__for_courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_removeCourseCalendarEvents__for_courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - } - - open func removeAllCourseCalendarEvents() { - addInvocation(.m_removeAllCourseCalendarEvents) - let perform = methodPerformValue(.m_removeAllCourseCalendarEvents) as? () -> Void - perform?() - } - - open func getCourseCalendarEvents(for courseId: String) -> [CourseCalendarEvent] { - addInvocation(.m_getCourseCalendarEvents__for_courseId(Parameter.value(`courseId`))) - let perform = methodPerformValue(.m_getCourseCalendarEvents__for_courseId(Parameter.value(`courseId`))) as? (String) -> Void - perform?(`courseId`) - var __value: [CourseCalendarEvent] - do { - __value = try methodReturnValue(.m_getCourseCalendarEvents__for_courseId(Parameter.value(`courseId`))).casted() - } catch { - onFatalFailure("Stub return value not specified for getCourseCalendarEvents(for courseId: String). Use given") - Failure("Stub return value not specified for getCourseCalendarEvents(for courseId: String). Use given") - } - return __value - } - - - fileprivate enum MethodType { - case m_getCourseState__courseID_courseID(Parameter) - case m_getAllCourseStates - case m_saveCourseState__state_state(Parameter) - case m_removeCourseState__courseID_courseID(Parameter) - case m_deleteAllCourseStatesAndEvents - case m_saveCourseCalendarEvent__event(Parameter) - case m_removeCourseCalendarEvents__for_courseId(Parameter) - case m_removeAllCourseCalendarEvents - case m_getCourseCalendarEvents__for_courseId(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_getCourseState__courseID_courseID(let lhsCourseid), .m_getCourseState__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_getAllCourseStates, .m_getAllCourseStates): return .match - - case (.m_saveCourseState__state_state(let lhsState), .m_saveCourseState__state_state(let rhsState)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsState, rhs: rhsState, with: matcher), lhsState, rhsState, "state")) - return Matcher.ComparisonResult(results) - - case (.m_removeCourseState__courseID_courseID(let lhsCourseid), .m_removeCourseState__courseID_courseID(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "courseID")) - return Matcher.ComparisonResult(results) - - case (.m_deleteAllCourseStatesAndEvents, .m_deleteAllCourseStatesAndEvents): return .match - - case (.m_saveCourseCalendarEvent__event(let lhsEvent), .m_saveCourseCalendarEvent__event(let rhsEvent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsEvent, rhs: rhsEvent, with: matcher), lhsEvent, rhsEvent, "_ event")) - return Matcher.ComparisonResult(results) - - case (.m_removeCourseCalendarEvents__for_courseId(let lhsCourseid), .m_removeCourseCalendarEvents__for_courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "for courseId")) - return Matcher.ComparisonResult(results) - - case (.m_removeAllCourseCalendarEvents, .m_removeAllCourseCalendarEvents): return .match - - case (.m_getCourseCalendarEvents__for_courseId(let lhsCourseid), .m_getCourseCalendarEvents__for_courseId(let rhsCourseid)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCourseid, rhs: rhsCourseid, with: matcher), lhsCourseid, rhsCourseid, "for courseId")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_getCourseState__courseID_courseID(p0): return p0.intValue - case .m_getAllCourseStates: return 0 - case let .m_saveCourseState__state_state(p0): return p0.intValue - case let .m_removeCourseState__courseID_courseID(p0): return p0.intValue - case .m_deleteAllCourseStatesAndEvents: return 0 - case let .m_saveCourseCalendarEvent__event(p0): return p0.intValue - case let .m_removeCourseCalendarEvents__for_courseId(p0): return p0.intValue - case .m_removeAllCourseCalendarEvents: return 0 - case let .m_getCourseCalendarEvents__for_courseId(p0): return p0.intValue - } - } - func assertionName() -> String { - switch self { - case .m_getCourseState__courseID_courseID: return ".getCourseState(courseID:)" - case .m_getAllCourseStates: return ".getAllCourseStates()" - case .m_saveCourseState__state_state: return ".saveCourseState(state:)" - case .m_removeCourseState__courseID_courseID: return ".removeCourseState(courseID:)" - case .m_deleteAllCourseStatesAndEvents: return ".deleteAllCourseStatesAndEvents()" - case .m_saveCourseCalendarEvent__event: return ".saveCourseCalendarEvent(_:)" - case .m_removeCourseCalendarEvents__for_courseId: return ".removeCourseCalendarEvents(for:)" - case .m_removeAllCourseCalendarEvents: return ".removeAllCourseCalendarEvents()" - case .m_getCourseCalendarEvents__for_courseId: return ".getCourseCalendarEvents(for:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - public static func getCourseState(courseID: Parameter, willReturn: CourseCalendarState?...) -> MethodStub { - return Given(method: .m_getCourseState__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getAllCourseStates(willReturn: [CourseCalendarState]...) -> MethodStub { - return Given(method: .m_getAllCourseStates, products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseCalendarEvents(for courseId: Parameter, willReturn: [CourseCalendarEvent]...) -> MethodStub { - return Given(method: .m_getCourseCalendarEvents__for_courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) - } - public static func getCourseState(courseID: Parameter, willProduce: (Stubber) -> Void) -> MethodStub { - let willReturn: [CourseCalendarState?] = [] - let given: Given = { return Given(method: .m_getCourseState__courseID_courseID(`courseID`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: (CourseCalendarState?).self) - willProduce(stubber) - return given - } - public static func getAllCourseStates(willProduce: (Stubber<[CourseCalendarState]>) -> Void) -> MethodStub { - let willReturn: [[CourseCalendarState]] = [] - let given: Given = { return Given(method: .m_getAllCourseStates, products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([CourseCalendarState]).self) - willProduce(stubber) - return given - } - public static func getCourseCalendarEvents(for courseId: Parameter, willProduce: (Stubber<[CourseCalendarEvent]>) -> Void) -> MethodStub { - let willReturn: [[CourseCalendarEvent]] = [] - let given: Given = { return Given(method: .m_getCourseCalendarEvents__for_courseId(`courseId`), products: willReturn.map({ StubProduct.return($0 as Any) })) }() - let stubber = given.stub(for: ([CourseCalendarEvent]).self) - willProduce(stubber) - return given - } - } - - public struct Verify { - fileprivate var method: MethodType - - public static func getCourseState(courseID: Parameter) -> Verify { return Verify(method: .m_getCourseState__courseID_courseID(`courseID`))} - public static func getAllCourseStates() -> Verify { return Verify(method: .m_getAllCourseStates)} - public static func saveCourseState(state: Parameter) -> Verify { return Verify(method: .m_saveCourseState__state_state(`state`))} - public static func removeCourseState(courseID: Parameter) -> Verify { return Verify(method: .m_removeCourseState__courseID_courseID(`courseID`))} - public static func deleteAllCourseStatesAndEvents() -> Verify { return Verify(method: .m_deleteAllCourseStatesAndEvents)} - public static func saveCourseCalendarEvent(_ event: Parameter) -> Verify { return Verify(method: .m_saveCourseCalendarEvent__event(`event`))} - public static func removeCourseCalendarEvents(for courseId: Parameter) -> Verify { return Verify(method: .m_removeCourseCalendarEvents__for_courseId(`courseId`))} - public static func removeAllCourseCalendarEvents() -> Verify { return Verify(method: .m_removeAllCourseCalendarEvents)} - public static func getCourseCalendarEvents(for courseId: Parameter) -> Verify { return Verify(method: .m_getCourseCalendarEvents__for_courseId(`courseId`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func getCourseState(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseState__courseID_courseID(`courseID`), performs: perform) - } - public static func getAllCourseStates(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_getAllCourseStates, performs: perform) - } - public static func saveCourseState(state: Parameter, perform: @escaping (CourseCalendarState) -> Void) -> Perform { - return Perform(method: .m_saveCourseState__state_state(`state`), performs: perform) - } - public static func removeCourseState(courseID: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_removeCourseState__courseID_courseID(`courseID`), performs: perform) - } - public static func deleteAllCourseStatesAndEvents(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_deleteAllCourseStatesAndEvents, performs: perform) - } - public static func saveCourseCalendarEvent(_ event: Parameter, perform: @escaping (CourseCalendarEvent) -> Void) -> Perform { - return Perform(method: .m_saveCourseCalendarEvent__event(`event`), performs: perform) - } - public static func removeCourseCalendarEvents(for courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_removeCourseCalendarEvents__for_courseId(`courseId`), performs: perform) - } - public static func removeAllCourseCalendarEvents(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_removeAllCourseCalendarEvents, performs: perform) - } - public static func getCourseCalendarEvents(for courseId: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_getCourseCalendarEvents__for_courseId(`courseId`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ProfileRouter -@MainActor -open class ProfileRouterMock: ProfileRouter, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func showEditProfile(userModel: Core.UserProfile, avatar: UIImage?, profileDidEdit: @escaping ((UserProfile?, UIImage?)) -> Void) { - addInvocation(.m_showEditProfile__userModel_userModelavatar_avatarprofileDidEdit_profileDidEdit(Parameter.value(`userModel`), Parameter.value(`avatar`), Parameter<((UserProfile?, UIImage?)) -> Void>.value(`profileDidEdit`))) - let perform = methodPerformValue(.m_showEditProfile__userModel_userModelavatar_avatarprofileDidEdit_profileDidEdit(Parameter.value(`userModel`), Parameter.value(`avatar`), Parameter<((UserProfile?, UIImage?)) -> Void>.value(`profileDidEdit`))) as? (Core.UserProfile, UIImage?, @escaping ((UserProfile?, UIImage?)) -> Void) -> Void - perform?(`userModel`, `avatar`, `profileDidEdit`) - } - - open func showSettings() { - addInvocation(.m_showSettings) - let perform = methodPerformValue(.m_showSettings) as? () -> Void - perform?() - } - - open func showVideoSettings() { - addInvocation(.m_showVideoSettings) - let perform = methodPerformValue(.m_showVideoSettings) as? () -> Void - perform?() - } - - open func showManageAccount() { - addInvocation(.m_showManageAccount) - let perform = methodPerformValue(.m_showManageAccount) as? () -> Void - perform?() - } - - open func showDatesAndCalendar() { - addInvocation(.m_showDatesAndCalendar) - let perform = methodPerformValue(.m_showDatesAndCalendar) as? () -> Void - perform?() - } - - open func showSyncCalendarOptions() { - addInvocation(.m_showSyncCalendarOptions) - let perform = methodPerformValue(.m_showSyncCalendarOptions) as? () -> Void - perform?() - } - - open func showCoursesToSync() { - addInvocation(.m_showCoursesToSync) - let perform = methodPerformValue(.m_showCoursesToSync) as? () -> Void - perform?() - } - - open func showVideoQualityView(viewModel: SettingsViewModel) { - addInvocation(.m_showVideoQualityView__viewModel_viewModel(Parameter.value(`viewModel`))) - let perform = methodPerformValue(.m_showVideoQualityView__viewModel_viewModel(Parameter.value(`viewModel`))) as? (SettingsViewModel) -> Void - perform?(`viewModel`) - } - - open func showVideoDownloadQualityView(downloadQuality: DownloadQuality, didSelect: ((DownloadQuality) -> Void)?, analytics: CoreAnalytics) { - addInvocation(.m_showVideoDownloadQualityView__downloadQuality_downloadQualitydidSelect_didSelectanalytics_analytics(Parameter.value(`downloadQuality`), Parameter<((DownloadQuality) -> Void)?>.value(`didSelect`), Parameter.value(`analytics`))) - let perform = methodPerformValue(.m_showVideoDownloadQualityView__downloadQuality_downloadQualitydidSelect_didSelectanalytics_analytics(Parameter.value(`downloadQuality`), Parameter<((DownloadQuality) -> Void)?>.value(`didSelect`), Parameter.value(`analytics`))) as? (DownloadQuality, ((DownloadQuality) -> Void)?, CoreAnalytics) -> Void - perform?(`downloadQuality`, `didSelect`, `analytics`) - } - - open func showDeleteProfileView() { - addInvocation(.m_showDeleteProfileView) - let perform = methodPerformValue(.m_showDeleteProfileView) as? () -> Void - perform?() - } - - open func backToRoot(animated: Bool) { - addInvocation(.m_backToRoot__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_backToRoot__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func back(animated: Bool) { - addInvocation(.m_back__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_back__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func backWithFade() { - addInvocation(.m_backWithFade) - let perform = methodPerformValue(.m_backWithFade) as? () -> Void - perform?() - } - - open func dismiss(animated: Bool) { - addInvocation(.m_dismiss__animated_animated(Parameter.value(`animated`))) - let perform = methodPerformValue(.m_dismiss__animated_animated(Parameter.value(`animated`))) as? (Bool) -> Void - perform?(`animated`) - } - - open func removeLastView(controllers: Int) { - addInvocation(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) - let perform = methodPerformValue(.m_removeLastView__controllers_controllers(Parameter.value(`controllers`))) as? (Int) -> Void - perform?(`controllers`) - } - - open func showMainOrWhatsNewScreen(sourceScreen: LogistrationSourceScreen, postLoginData: PostLoginData?) { - addInvocation(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) - let perform = methodPerformValue(.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter.value(`sourceScreen`), Parameter.value(`postLoginData`))) as? (LogistrationSourceScreen, PostLoginData?) -> Void - perform?(`sourceScreen`, `postLoginData`) - } - - open func showStartupScreen() { - addInvocation(.m_showStartupScreen) - let perform = methodPerformValue(.m_showStartupScreen) as? () -> Void - perform?() - } - - open func showLoginScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showLoginScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showRegisterScreen(sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showRegisterScreen__sourceScreen_sourceScreen(Parameter.value(`sourceScreen`))) as? (LogistrationSourceScreen) -> Void - perform?(`sourceScreen`) - } - - open func showForgotPasswordScreen() { - addInvocation(.m_showForgotPasswordScreen) - let perform = methodPerformValue(.m_showForgotPasswordScreen) as? () -> Void - perform?() - } - - open func showDiscoveryScreen(searchQuery: String?, sourceScreen: LogistrationSourceScreen) { - addInvocation(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) - let perform = methodPerformValue(.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter.value(`searchQuery`), Parameter.value(`sourceScreen`))) as? (String?, LogistrationSourceScreen) -> Void - perform?(`searchQuery`, `sourceScreen`) - } - - open func showWebBrowser(title: String, url: URL) { - addInvocation(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) - let perform = methodPerformValue(.m_showWebBrowser__title_titleurl_url(Parameter.value(`title`), Parameter.value(`url`))) as? (String, URL) -> Void - perform?(`title`, `url`) - } - - open func showSSOWebBrowser(title: String) { - addInvocation(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) - let perform = methodPerformValue(.m_showSSOWebBrowser__title_title(Parameter.value(`title`))) as? (String) -> Void - perform?(`title`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, positiveAction: String, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, type: AlertViewType) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`positiveAction`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter.value(`type`))) as? (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void - perform?(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`) - } - - open func presentAlert(alertTitle: String, alertMessage: String, nextSectionName: String?, action: String, image: SwiftUI.Image, onCloseTapped: @escaping () -> Void, firstButtonTapped: @escaping () -> Void, nextSectionTapped: @escaping () -> Void) { - addInvocation(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) - let perform = methodPerformValue(.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter.value(`alertTitle`), Parameter.value(`alertMessage`), Parameter.value(`nextSectionName`), Parameter.value(`action`), Parameter.value(`image`), Parameter<() -> Void>.value(`onCloseTapped`), Parameter<() -> Void>.value(`firstButtonTapped`), Parameter<() -> Void>.value(`nextSectionTapped`))) as? (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void - perform?(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, view: any View, completion: (() -> Void)?) { - addInvocation(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter.value(`transitionStyle`), Parameter.value(`view`), Parameter<(() -> Void)?>.value(`completion`))) as? (UIModalTransitionStyle, any View, (() -> Void)?) -> Void - perform?(`transitionStyle`, `view`, `completion`) - } - - open func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) { - addInvocation(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) - let perform = methodPerformValue(.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter.value(`transitionStyle`), Parameter.value(`animated`), Parameter<() -> any View>.any)) as? (UIModalTransitionStyle, Bool, () -> any View) -> Void - perform?(`transitionStyle`, `animated`, `content`) - } - - - fileprivate enum MethodType { - case m_showEditProfile__userModel_userModelavatar_avatarprofileDidEdit_profileDidEdit(Parameter, Parameter, Parameter<((UserProfile?, UIImage?)) -> Void>) - case m_showSettings - case m_showVideoSettings - case m_showManageAccount - case m_showDatesAndCalendar - case m_showSyncCalendarOptions - case m_showCoursesToSync - case m_showVideoQualityView__viewModel_viewModel(Parameter) - case m_showVideoDownloadQualityView__downloadQuality_downloadQualitydidSelect_didSelectanalytics_analytics(Parameter, Parameter<((DownloadQuality) -> Void)?>, Parameter) - case m_showDeleteProfileView - case m_backToRoot__animated_animated(Parameter) - case m_back__animated_animated(Parameter) - case m_backWithFade - case m_dismiss__animated_animated(Parameter) - case m_removeLastView__controllers_controllers(Parameter) - case m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(Parameter, Parameter) - case m_showStartupScreen - case m_showLoginScreen__sourceScreen_sourceScreen(Parameter) - case m_showRegisterScreen__sourceScreen_sourceScreen(Parameter) - case m_showForgotPasswordScreen - case m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(Parameter, Parameter) - case m_showWebBrowser__title_titleurl_url(Parameter, Parameter) - case m_showSSOWebBrowser__title_title(Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter) - case m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(Parameter, Parameter, Parameter, Parameter, Parameter, Parameter<() -> Void>, Parameter<() -> Void>, Parameter<() -> Void>) - case m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(Parameter, Parameter, Parameter<(() -> Void)?>) - case m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(Parameter, Parameter, Parameter<() -> any View>) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_showEditProfile__userModel_userModelavatar_avatarprofileDidEdit_profileDidEdit(let lhsUsermodel, let lhsAvatar, let lhsProfiledidedit), .m_showEditProfile__userModel_userModelavatar_avatarprofileDidEdit_profileDidEdit(let rhsUsermodel, let rhsAvatar, let rhsProfiledidedit)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUsermodel, rhs: rhsUsermodel, with: matcher), lhsUsermodel, rhsUsermodel, "userModel")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAvatar, rhs: rhsAvatar, with: matcher), lhsAvatar, rhsAvatar, "avatar")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsProfiledidedit, rhs: rhsProfiledidedit, with: matcher), lhsProfiledidedit, rhsProfiledidedit, "profileDidEdit")) - return Matcher.ComparisonResult(results) - - case (.m_showSettings, .m_showSettings): return .match - - case (.m_showVideoSettings, .m_showVideoSettings): return .match - - case (.m_showManageAccount, .m_showManageAccount): return .match - - case (.m_showDatesAndCalendar, .m_showDatesAndCalendar): return .match - - case (.m_showSyncCalendarOptions, .m_showSyncCalendarOptions): return .match - - case (.m_showCoursesToSync, .m_showCoursesToSync): return .match - - case (.m_showVideoQualityView__viewModel_viewModel(let lhsViewmodel), .m_showVideoQualityView__viewModel_viewModel(let rhsViewmodel)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsViewmodel, rhs: rhsViewmodel, with: matcher), lhsViewmodel, rhsViewmodel, "viewModel")) - return Matcher.ComparisonResult(results) - - case (.m_showVideoDownloadQualityView__downloadQuality_downloadQualitydidSelect_didSelectanalytics_analytics(let lhsDownloadquality, let lhsDidselect, let lhsAnalytics), .m_showVideoDownloadQualityView__downloadQuality_downloadQualitydidSelect_didSelectanalytics_analytics(let rhsDownloadquality, let rhsDidselect, let rhsAnalytics)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDownloadquality, rhs: rhsDownloadquality, with: matcher), lhsDownloadquality, rhsDownloadquality, "downloadQuality")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsDidselect, rhs: rhsDidselect, with: matcher), lhsDidselect, rhsDidselect, "didSelect")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnalytics, rhs: rhsAnalytics, with: matcher), lhsAnalytics, rhsAnalytics, "analytics")) - return Matcher.ComparisonResult(results) - - case (.m_showDeleteProfileView, .m_showDeleteProfileView): return .match - - case (.m_backToRoot__animated_animated(let lhsAnimated), .m_backToRoot__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_back__animated_animated(let lhsAnimated), .m_back__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_backWithFade, .m_backWithFade): return .match - - case (.m_dismiss__animated_animated(let lhsAnimated), .m_dismiss__animated_animated(let rhsAnimated)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - return Matcher.ComparisonResult(results) - - case (.m_removeLastView__controllers_controllers(let lhsControllers), .m_removeLastView__controllers_controllers(let rhsControllers)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsControllers, rhs: rhsControllers, with: matcher), lhsControllers, rhsControllers, "controllers")) - return Matcher.ComparisonResult(results) - - case (.m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let lhsSourcescreen, let lhsPostlogindata), .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(let rhsSourcescreen, let rhsPostlogindata)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPostlogindata, rhs: rhsPostlogindata, with: matcher), lhsPostlogindata, rhsPostlogindata, "postLoginData")) - return Matcher.ComparisonResult(results) - - case (.m_showStartupScreen, .m_showStartupScreen): return .match - - case (.m_showLoginScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showLoginScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showRegisterScreen__sourceScreen_sourceScreen(let lhsSourcescreen), .m_showRegisterScreen__sourceScreen_sourceScreen(let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showForgotPasswordScreen, .m_showForgotPasswordScreen): return .match - - case (.m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let lhsSearchquery, let lhsSourcescreen), .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(let rhsSearchquery, let rhsSourcescreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSearchquery, rhs: rhsSearchquery, with: matcher), lhsSearchquery, rhsSearchquery, "searchQuery")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsSourcescreen, rhs: rhsSourcescreen, with: matcher), lhsSourcescreen, rhsSourcescreen, "sourceScreen")) - return Matcher.ComparisonResult(results) - - case (.m_showWebBrowser__title_titleurl_url(let lhsTitle, let lhsUrl), .m_showWebBrowser__title_titleurl_url(let rhsTitle, let rhsUrl)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsUrl, rhs: rhsUrl, with: matcher), lhsUrl, rhsUrl, "url")) - return Matcher.ComparisonResult(results) - - case (.m_showSSOWebBrowser__title_title(let lhsTitle), .m_showSSOWebBrowser__title_title(let rhsTitle)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTitle, rhs: rhsTitle, with: matcher), lhsTitle, rhsTitle, "title")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let lhsAlerttitle, let lhsAlertmessage, let lhsPositiveaction, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsType), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(let rhsAlerttitle, let rhsAlertmessage, let rhsPositiveaction, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsType)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsPositiveaction, rhs: rhsPositiveaction, with: matcher), lhsPositiveaction, rhsPositiveaction, "positiveAction")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsType, rhs: rhsType, with: matcher), lhsType, rhsType, "type")) - return Matcher.ComparisonResult(results) - - case (.m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let lhsAlerttitle, let lhsAlertmessage, let lhsNextsectionname, let lhsAction, let lhsImage, let lhsOnclosetapped, let lhsFirstbuttontapped, let lhsNextsectiontapped), .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(let rhsAlerttitle, let rhsAlertmessage, let rhsNextsectionname, let rhsAction, let rhsImage, let rhsOnclosetapped, let rhsFirstbuttontapped, let rhsNextsectiontapped)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlerttitle, rhs: rhsAlerttitle, with: matcher), lhsAlerttitle, rhsAlerttitle, "alertTitle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAlertmessage, rhs: rhsAlertmessage, with: matcher), lhsAlertmessage, rhsAlertmessage, "alertMessage")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectionname, rhs: rhsNextsectionname, with: matcher), lhsNextsectionname, rhsNextsectionname, "nextSectionName")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAction, rhs: rhsAction, with: matcher), lhsAction, rhsAction, "action")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsImage, rhs: rhsImage, with: matcher), lhsImage, rhsImage, "image")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsOnclosetapped, rhs: rhsOnclosetapped, with: matcher), lhsOnclosetapped, rhsOnclosetapped, "onCloseTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsFirstbuttontapped, rhs: rhsFirstbuttontapped, with: matcher), lhsFirstbuttontapped, rhsFirstbuttontapped, "firstButtonTapped")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsNextsectiontapped, rhs: rhsNextsectiontapped, with: matcher), lhsNextsectiontapped, rhsNextsectiontapped, "nextSectionTapped")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let lhsTransitionstyle, let lhsView, let lhsCompletion), .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(let rhsTransitionstyle, let rhsView, let rhsCompletion)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsView, rhs: rhsView, with: matcher), lhsView, rhsView, "view")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCompletion, rhs: rhsCompletion, with: matcher), lhsCompletion, rhsCompletion, "completion")) - return Matcher.ComparisonResult(results) - - case (.m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let lhsTransitionstyle, let lhsAnimated, let lhsContent), .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(let rhsTransitionstyle, let rhsAnimated, let rhsContent)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTransitionstyle, rhs: rhsTransitionstyle, with: matcher), lhsTransitionstyle, rhsTransitionstyle, "transitionStyle")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsAnimated, rhs: rhsAnimated, with: matcher), lhsAnimated, rhsAnimated, "animated")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsContent, rhs: rhsContent, with: matcher), lhsContent, rhsContent, "content")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case let .m_showEditProfile__userModel_userModelavatar_avatarprofileDidEdit_profileDidEdit(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case .m_showSettings: return 0 - case .m_showVideoSettings: return 0 - case .m_showManageAccount: return 0 - case .m_showDatesAndCalendar: return 0 - case .m_showSyncCalendarOptions: return 0 - case .m_showCoursesToSync: return 0 - case let .m_showVideoQualityView__viewModel_viewModel(p0): return p0.intValue - case let .m_showVideoDownloadQualityView__downloadQuality_downloadQualitydidSelect_didSelectanalytics_analytics(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case .m_showDeleteProfileView: return 0 - case let .m_backToRoot__animated_animated(p0): return p0.intValue - case let .m_back__animated_animated(p0): return p0.intValue - case .m_backWithFade: return 0 - case let .m_dismiss__animated_animated(p0): return p0.intValue - case let .m_removeLastView__controllers_controllers(p0): return p0.intValue - case let .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(p0, p1): return p0.intValue + p1.intValue - case .m_showStartupScreen: return 0 - case let .m_showLoginScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case let .m_showRegisterScreen__sourceScreen_sourceScreen(p0): return p0.intValue - case .m_showForgotPasswordScreen: return 0 - case let .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(p0, p1): return p0.intValue + p1.intValue - case let .m_showWebBrowser__title_titleurl_url(p0, p1): return p0.intValue + p1.intValue - case let .m_showSSOWebBrowser__title_title(p0): return p0.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(p0, p1, p2, p3, p4, p5): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue - case let .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(p0, p1, p2, p3, p4, p5, p6, p7): return p0.intValue + p1.intValue + p2.intValue + p3.intValue + p4.intValue + p5.intValue + p6.intValue + p7.intValue - case let .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - case let .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(p0, p1, p2): return p0.intValue + p1.intValue + p2.intValue - } - } - func assertionName() -> String { - switch self { - case .m_showEditProfile__userModel_userModelavatar_avatarprofileDidEdit_profileDidEdit: return ".showEditProfile(userModel:avatar:profileDidEdit:)" - case .m_showSettings: return ".showSettings()" - case .m_showVideoSettings: return ".showVideoSettings()" - case .m_showManageAccount: return ".showManageAccount()" - case .m_showDatesAndCalendar: return ".showDatesAndCalendar()" - case .m_showSyncCalendarOptions: return ".showSyncCalendarOptions()" - case .m_showCoursesToSync: return ".showCoursesToSync()" - case .m_showVideoQualityView__viewModel_viewModel: return ".showVideoQualityView(viewModel:)" - case .m_showVideoDownloadQualityView__downloadQuality_downloadQualitydidSelect_didSelectanalytics_analytics: return ".showVideoDownloadQualityView(downloadQuality:didSelect:analytics:)" - case .m_showDeleteProfileView: return ".showDeleteProfileView()" - case .m_backToRoot__animated_animated: return ".backToRoot(animated:)" - case .m_back__animated_animated: return ".back(animated:)" - case .m_backWithFade: return ".backWithFade()" - case .m_dismiss__animated_animated: return ".dismiss(animated:)" - case .m_removeLastView__controllers_controllers: return ".removeLastView(controllers:)" - case .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData: return ".showMainOrWhatsNewScreen(sourceScreen:postLoginData:)" - case .m_showStartupScreen: return ".showStartupScreen()" - case .m_showLoginScreen__sourceScreen_sourceScreen: return ".showLoginScreen(sourceScreen:)" - case .m_showRegisterScreen__sourceScreen_sourceScreen: return ".showRegisterScreen(sourceScreen:)" - case .m_showForgotPasswordScreen: return ".showForgotPasswordScreen()" - case .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen: return ".showDiscoveryScreen(searchQuery:sourceScreen:)" - case .m_showWebBrowser__title_titleurl_url: return ".showWebBrowser(title:url:)" - case .m_showSSOWebBrowser__title_title: return ".showSSOWebBrowser(title:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type: return ".presentAlert(alertTitle:alertMessage:positiveAction:onCloseTapped:firstButtonTapped:type:)" - case .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped: return ".presentAlert(alertTitle:alertMessage:nextSectionName:action:image:onCloseTapped:firstButtonTapped:nextSectionTapped:)" - case .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion: return ".presentView(transitionStyle:view:completion:)" - case .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content: return ".presentView(transitionStyle:animated:content:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func showEditProfile(userModel: Parameter, avatar: Parameter, profileDidEdit: Parameter<((UserProfile?, UIImage?)) -> Void>) -> Verify { return Verify(method: .m_showEditProfile__userModel_userModelavatar_avatarprofileDidEdit_profileDidEdit(`userModel`, `avatar`, `profileDidEdit`))} - public static func showSettings() -> Verify { return Verify(method: .m_showSettings)} - public static func showVideoSettings() -> Verify { return Verify(method: .m_showVideoSettings)} - public static func showManageAccount() -> Verify { return Verify(method: .m_showManageAccount)} - public static func showDatesAndCalendar() -> Verify { return Verify(method: .m_showDatesAndCalendar)} - public static func showSyncCalendarOptions() -> Verify { return Verify(method: .m_showSyncCalendarOptions)} - public static func showCoursesToSync() -> Verify { return Verify(method: .m_showCoursesToSync)} - public static func showVideoQualityView(viewModel: Parameter) -> Verify { return Verify(method: .m_showVideoQualityView__viewModel_viewModel(`viewModel`))} - public static func showVideoDownloadQualityView(downloadQuality: Parameter, didSelect: Parameter<((DownloadQuality) -> Void)?>, analytics: Parameter) -> Verify { return Verify(method: .m_showVideoDownloadQualityView__downloadQuality_downloadQualitydidSelect_didSelectanalytics_analytics(`downloadQuality`, `didSelect`, `analytics`))} - public static func showDeleteProfileView() -> Verify { return Verify(method: .m_showDeleteProfileView)} - public static func backToRoot(animated: Parameter) -> Verify { return Verify(method: .m_backToRoot__animated_animated(`animated`))} - public static func back(animated: Parameter) -> Verify { return Verify(method: .m_back__animated_animated(`animated`))} - public static func backWithFade() -> Verify { return Verify(method: .m_backWithFade)} - public static func dismiss(animated: Parameter) -> Verify { return Verify(method: .m_dismiss__animated_animated(`animated`))} - public static func removeLastView(controllers: Parameter) -> Verify { return Verify(method: .m_removeLastView__controllers_controllers(`controllers`))} - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter) -> Verify { return Verify(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`))} - public static func showStartupScreen() -> Verify { return Verify(method: .m_showStartupScreen)} - public static func showLoginScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showRegisterScreen(sourceScreen: Parameter) -> Verify { return Verify(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`))} - public static func showForgotPasswordScreen() -> Verify { return Verify(method: .m_showForgotPasswordScreen)} - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter) -> Verify { return Verify(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`))} - public static func showWebBrowser(title: Parameter, url: Parameter) -> Verify { return Verify(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`))} - public static func showSSOWebBrowser(title: Parameter) -> Verify { return Verify(method: .m_showSSOWebBrowser__title_title(`title`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`))} - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>) -> Verify { return Verify(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`))} - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`))} - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>) -> Verify { return Verify(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func showEditProfile(userModel: Parameter, avatar: Parameter, profileDidEdit: Parameter<((UserProfile?, UIImage?)) -> Void>, perform: @escaping (Core.UserProfile, UIImage?, @escaping ((UserProfile?, UIImage?)) -> Void) -> Void) -> Perform { - return Perform(method: .m_showEditProfile__userModel_userModelavatar_avatarprofileDidEdit_profileDidEdit(`userModel`, `avatar`, `profileDidEdit`), performs: perform) - } - public static func showSettings(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showSettings, performs: perform) - } - public static func showVideoSettings(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showVideoSettings, performs: perform) - } - public static func showManageAccount(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showManageAccount, performs: perform) - } - public static func showDatesAndCalendar(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showDatesAndCalendar, performs: perform) - } - public static func showSyncCalendarOptions(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showSyncCalendarOptions, performs: perform) - } - public static func showCoursesToSync(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showCoursesToSync, performs: perform) - } - public static func showVideoQualityView(viewModel: Parameter, perform: @escaping (SettingsViewModel) -> Void) -> Perform { - return Perform(method: .m_showVideoQualityView__viewModel_viewModel(`viewModel`), performs: perform) - } - public static func showVideoDownloadQualityView(downloadQuality: Parameter, didSelect: Parameter<((DownloadQuality) -> Void)?>, analytics: Parameter, perform: @escaping (DownloadQuality, ((DownloadQuality) -> Void)?, CoreAnalytics) -> Void) -> Perform { - return Perform(method: .m_showVideoDownloadQualityView__downloadQuality_downloadQualitydidSelect_didSelectanalytics_analytics(`downloadQuality`, `didSelect`, `analytics`), performs: perform) - } - public static func showDeleteProfileView(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showDeleteProfileView, performs: perform) - } - public static func backToRoot(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_backToRoot__animated_animated(`animated`), performs: perform) - } - public static func back(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_back__animated_animated(`animated`), performs: perform) - } - public static func backWithFade(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_backWithFade, performs: perform) - } - public static func dismiss(animated: Parameter, perform: @escaping (Bool) -> Void) -> Perform { - return Perform(method: .m_dismiss__animated_animated(`animated`), performs: perform) - } - public static func removeLastView(controllers: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_removeLastView__controllers_controllers(`controllers`), performs: perform) - } - public static func showMainOrWhatsNewScreen(sourceScreen: Parameter, postLoginData: Parameter, perform: @escaping (LogistrationSourceScreen, PostLoginData?) -> Void) -> Perform { - return Perform(method: .m_showMainOrWhatsNewScreen__sourceScreen_sourceScreenpostLoginData_postLoginData(`sourceScreen`, `postLoginData`), performs: perform) - } - public static func showStartupScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showStartupScreen, performs: perform) - } - public static func showLoginScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showLoginScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showRegisterScreen(sourceScreen: Parameter, perform: @escaping (LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showRegisterScreen__sourceScreen_sourceScreen(`sourceScreen`), performs: perform) - } - public static func showForgotPasswordScreen(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_showForgotPasswordScreen, performs: perform) - } - public static func showDiscoveryScreen(searchQuery: Parameter, sourceScreen: Parameter, perform: @escaping (String?, LogistrationSourceScreen) -> Void) -> Perform { - return Perform(method: .m_showDiscoveryScreen__searchQuery_searchQuerysourceScreen_sourceScreen(`searchQuery`, `sourceScreen`), performs: perform) - } - public static func showWebBrowser(title: Parameter, url: Parameter, perform: @escaping (String, URL) -> Void) -> Perform { - return Perform(method: .m_showWebBrowser__title_titleurl_url(`title`, `url`), performs: perform) - } - public static func showSSOWebBrowser(title: Parameter, perform: @escaping (String) -> Void) -> Perform { - return Perform(method: .m_showSSOWebBrowser__title_title(`title`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, positiveAction: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, type: Parameter, perform: @escaping (String, String, String, @escaping () -> Void, @escaping () -> Void, AlertViewType) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagepositiveAction_positiveActiononCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappedtype_type(`alertTitle`, `alertMessage`, `positiveAction`, `onCloseTapped`, `firstButtonTapped`, `type`), performs: perform) - } - public static func presentAlert(alertTitle: Parameter, alertMessage: Parameter, nextSectionName: Parameter, action: Parameter, image: Parameter, onCloseTapped: Parameter<() -> Void>, firstButtonTapped: Parameter<() -> Void>, nextSectionTapped: Parameter<() -> Void>, perform: @escaping (String, String, String?, String, SwiftUI.Image, @escaping () -> Void, @escaping () -> Void, @escaping () -> Void) -> Void) -> Perform { - return Perform(method: .m_presentAlert__alertTitle_alertTitlealertMessage_alertMessagenextSectionName_nextSectionNameaction_actionimage_imageonCloseTapped_onCloseTappedfirstButtonTapped_firstButtonTappednextSectionTapped_nextSectionTapped(`alertTitle`, `alertMessage`, `nextSectionName`, `action`, `image`, `onCloseTapped`, `firstButtonTapped`, `nextSectionTapped`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, view: Parameter, completion: Parameter<(() -> Void)?>, perform: @escaping (UIModalTransitionStyle, any View, (() -> Void)?) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleview_viewcompletion_completion(`transitionStyle`, `view`, `completion`), performs: perform) - } - public static func presentView(transitionStyle: Parameter, animated: Parameter, content: Parameter<() -> any View>, perform: @escaping (UIModalTransitionStyle, Bool, () -> any View) -> Void) -> Perform { - return Perform(method: .m_presentView__transitionStyle_transitionStyleanimated_animatedcontent_content(`transitionStyle`, `animated`, `content`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - -// MARK: - ProfileStorage - -open class ProfileStorageMock: ProfileStorage, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - public var userProfile: DataLayer.UserProfile? { - get { invocations.append(.p_userProfile_get); return __p_userProfile ?? optionalGivenGetterValue(.p_userProfile_get, "ProfileStorageMock - stub value for userProfile was not defined") } - set { invocations.append(.p_userProfile_set(.value(newValue))); __p_userProfile = newValue } - } - private var __p_userProfile: (DataLayer.UserProfile)? - - public var useRelativeDates: Bool { - get { invocations.append(.p_useRelativeDates_get); return __p_useRelativeDates ?? givenGetterValue(.p_useRelativeDates_get, "ProfileStorageMock - stub value for useRelativeDates was not defined") } - set { invocations.append(.p_useRelativeDates_set(.value(newValue))); __p_useRelativeDates = newValue } - } - private var __p_useRelativeDates: (Bool)? - - public var calendarSettings: CalendarSettings? { - get { invocations.append(.p_calendarSettings_get); return __p_calendarSettings ?? optionalGivenGetterValue(.p_calendarSettings_get, "ProfileStorageMock - stub value for calendarSettings was not defined") } - set { invocations.append(.p_calendarSettings_set(.value(newValue))); __p_calendarSettings = newValue } - } - private var __p_calendarSettings: (CalendarSettings)? - - public var hideInactiveCourses: Bool? { - get { invocations.append(.p_hideInactiveCourses_get); return __p_hideInactiveCourses ?? optionalGivenGetterValue(.p_hideInactiveCourses_get, "ProfileStorageMock - stub value for hideInactiveCourses was not defined") } - set { invocations.append(.p_hideInactiveCourses_set(.value(newValue))); __p_hideInactiveCourses = newValue } - } - private var __p_hideInactiveCourses: (Bool)? - - public var lastLoginUsername: String? { - get { invocations.append(.p_lastLoginUsername_get); return __p_lastLoginUsername ?? optionalGivenGetterValue(.p_lastLoginUsername_get, "ProfileStorageMock - stub value for lastLoginUsername was not defined") } - set { invocations.append(.p_lastLoginUsername_set(.value(newValue))); __p_lastLoginUsername = newValue } - } - private var __p_lastLoginUsername: (String)? - - public var lastCalendarName: String? { - get { invocations.append(.p_lastCalendarName_get); return __p_lastCalendarName ?? optionalGivenGetterValue(.p_lastCalendarName_get, "ProfileStorageMock - stub value for lastCalendarName was not defined") } - set { invocations.append(.p_lastCalendarName_set(.value(newValue))); __p_lastCalendarName = newValue } - } - private var __p_lastCalendarName: (String)? - - public var lastCalendarUpdateDate: Date? { - get { invocations.append(.p_lastCalendarUpdateDate_get); return __p_lastCalendarUpdateDate ?? optionalGivenGetterValue(.p_lastCalendarUpdateDate_get, "ProfileStorageMock - stub value for lastCalendarUpdateDate was not defined") } - set { invocations.append(.p_lastCalendarUpdateDate_set(.value(newValue))); __p_lastCalendarUpdateDate = newValue } - } - private var __p_lastCalendarUpdateDate: (Date)? - - public var firstCalendarUpdate: Bool? { - get { invocations.append(.p_firstCalendarUpdate_get); return __p_firstCalendarUpdate ?? optionalGivenGetterValue(.p_firstCalendarUpdate_get, "ProfileStorageMock - stub value for firstCalendarUpdate was not defined") } - set { invocations.append(.p_firstCalendarUpdate_set(.value(newValue))); __p_firstCalendarUpdate = newValue } - } - private var __p_firstCalendarUpdate: (Bool)? - - - - - - - fileprivate enum MethodType { - case p_userProfile_get - case p_userProfile_set(Parameter) - case p_useRelativeDates_get - case p_useRelativeDates_set(Parameter) - case p_calendarSettings_get - case p_calendarSettings_set(Parameter) - case p_hideInactiveCourses_get - case p_hideInactiveCourses_set(Parameter) - case p_lastLoginUsername_get - case p_lastLoginUsername_set(Parameter) - case p_lastCalendarName_get - case p_lastCalendarName_set(Parameter) - case p_lastCalendarUpdateDate_get - case p_lastCalendarUpdateDate_set(Parameter) - case p_firstCalendarUpdate_get - case p_firstCalendarUpdate_set(Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { case (.p_userProfile_get,.p_userProfile_get): return Matcher.ComparisonResult.match - case (.p_userProfile_set(let left),.p_userProfile_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_useRelativeDates_get,.p_useRelativeDates_get): return Matcher.ComparisonResult.match - case (.p_useRelativeDates_set(let left),.p_useRelativeDates_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_calendarSettings_get,.p_calendarSettings_get): return Matcher.ComparisonResult.match - case (.p_calendarSettings_set(let left),.p_calendarSettings_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_hideInactiveCourses_get,.p_hideInactiveCourses_get): return Matcher.ComparisonResult.match - case (.p_hideInactiveCourses_set(let left),.p_hideInactiveCourses_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastLoginUsername_get,.p_lastLoginUsername_get): return Matcher.ComparisonResult.match - case (.p_lastLoginUsername_set(let left),.p_lastLoginUsername_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastCalendarName_get,.p_lastCalendarName_get): return Matcher.ComparisonResult.match - case (.p_lastCalendarName_set(let left),.p_lastCalendarName_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_lastCalendarUpdateDate_get,.p_lastCalendarUpdateDate_get): return Matcher.ComparisonResult.match - case (.p_lastCalendarUpdateDate_set(let left),.p_lastCalendarUpdateDate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - case (.p_firstCalendarUpdate_get,.p_firstCalendarUpdate_get): return Matcher.ComparisonResult.match - case (.p_firstCalendarUpdate_set(let left),.p_firstCalendarUpdate_set(let right)): return Matcher.ComparisonResult([Matcher.ParameterComparisonResult(Parameter.compare(lhs: left, rhs: right, with: matcher), left, right, "newValue")]) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .p_userProfile_get: return 0 - case .p_userProfile_set(let newValue): return newValue.intValue - case .p_useRelativeDates_get: return 0 - case .p_useRelativeDates_set(let newValue): return newValue.intValue - case .p_calendarSettings_get: return 0 - case .p_calendarSettings_set(let newValue): return newValue.intValue - case .p_hideInactiveCourses_get: return 0 - case .p_hideInactiveCourses_set(let newValue): return newValue.intValue - case .p_lastLoginUsername_get: return 0 - case .p_lastLoginUsername_set(let newValue): return newValue.intValue - case .p_lastCalendarName_get: return 0 - case .p_lastCalendarName_set(let newValue): return newValue.intValue - case .p_lastCalendarUpdateDate_get: return 0 - case .p_lastCalendarUpdateDate_set(let newValue): return newValue.intValue - case .p_firstCalendarUpdate_get: return 0 - case .p_firstCalendarUpdate_set(let newValue): return newValue.intValue - } - } - func assertionName() -> String { - switch self { - case .p_userProfile_get: return "[get] .userProfile" - case .p_userProfile_set: return "[set] .userProfile" - case .p_useRelativeDates_get: return "[get] .useRelativeDates" - case .p_useRelativeDates_set: return "[set] .useRelativeDates" - case .p_calendarSettings_get: return "[get] .calendarSettings" - case .p_calendarSettings_set: return "[set] .calendarSettings" - case .p_hideInactiveCourses_get: return "[get] .hideInactiveCourses" - case .p_hideInactiveCourses_set: return "[set] .hideInactiveCourses" - case .p_lastLoginUsername_get: return "[get] .lastLoginUsername" - case .p_lastLoginUsername_set: return "[set] .lastLoginUsername" - case .p_lastCalendarName_get: return "[get] .lastCalendarName" - case .p_lastCalendarName_set: return "[set] .lastCalendarName" - case .p_lastCalendarUpdateDate_get: return "[get] .lastCalendarUpdateDate" - case .p_lastCalendarUpdateDate_set: return "[set] .lastCalendarUpdateDate" - case .p_firstCalendarUpdate_get: return "[get] .firstCalendarUpdate" - case .p_firstCalendarUpdate_set: return "[set] .firstCalendarUpdate" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - public static func userProfile(getter defaultValue: DataLayer.UserProfile?...) -> PropertyStub { - return Given(method: .p_userProfile_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func useRelativeDates(getter defaultValue: Bool...) -> PropertyStub { - return Given(method: .p_useRelativeDates_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func calendarSettings(getter defaultValue: CalendarSettings?...) -> PropertyStub { - return Given(method: .p_calendarSettings_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func hideInactiveCourses(getter defaultValue: Bool?...) -> PropertyStub { - return Given(method: .p_hideInactiveCourses_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastLoginUsername(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_lastLoginUsername_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastCalendarName(getter defaultValue: String?...) -> PropertyStub { - return Given(method: .p_lastCalendarName_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func lastCalendarUpdateDate(getter defaultValue: Date?...) -> PropertyStub { - return Given(method: .p_lastCalendarUpdateDate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - public static func firstCalendarUpdate(getter defaultValue: Bool?...) -> PropertyStub { - return Given(method: .p_firstCalendarUpdate_get, products: defaultValue.map({ StubProduct.return($0 as Any) })) - } - - } - - public struct Verify { - fileprivate var method: MethodType - - public static var userProfile: Verify { return Verify(method: .p_userProfile_get) } - public static func userProfile(set newValue: Parameter) -> Verify { return Verify(method: .p_userProfile_set(newValue)) } - public static var useRelativeDates: Verify { return Verify(method: .p_useRelativeDates_get) } - public static func useRelativeDates(set newValue: Parameter) -> Verify { return Verify(method: .p_useRelativeDates_set(newValue)) } - public static var calendarSettings: Verify { return Verify(method: .p_calendarSettings_get) } - public static func calendarSettings(set newValue: Parameter) -> Verify { return Verify(method: .p_calendarSettings_set(newValue)) } - public static var hideInactiveCourses: Verify { return Verify(method: .p_hideInactiveCourses_get) } - public static func hideInactiveCourses(set newValue: Parameter) -> Verify { return Verify(method: .p_hideInactiveCourses_set(newValue)) } - public static var lastLoginUsername: Verify { return Verify(method: .p_lastLoginUsername_get) } - public static func lastLoginUsername(set newValue: Parameter) -> Verify { return Verify(method: .p_lastLoginUsername_set(newValue)) } - public static var lastCalendarName: Verify { return Verify(method: .p_lastCalendarName_get) } - public static func lastCalendarName(set newValue: Parameter) -> Verify { return Verify(method: .p_lastCalendarName_set(newValue)) } - public static var lastCalendarUpdateDate: Verify { return Verify(method: .p_lastCalendarUpdateDate_get) } - public static func lastCalendarUpdateDate(set newValue: Parameter) -> Verify { return Verify(method: .p_lastCalendarUpdateDate_set(newValue)) } - public static var firstCalendarUpdate: Verify { return Verify(method: .p_firstCalendarUpdate_get) } - public static func firstCalendarUpdate(set newValue: Parameter) -> Verify { return Verify(method: .p_firstCalendarUpdate_set(newValue)) } - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - diff --git a/Theme/Theme.xcodeproj/project.pbxproj b/Theme/Theme.xcodeproj/project.pbxproj index 1fc77b799..c064c986a 100644 --- a/Theme/Theme.xcodeproj/project.pbxproj +++ b/Theme/Theme.xcodeproj/project.pbxproj @@ -243,7 +243,6 @@ E0D6E6AA2B16EA380089F9C9 /* Sources */, E0D6E6AB2B16EA380089F9C9 /* Frameworks */, E0D6E6AC2B16EA380089F9C9 /* Resources */, - D1CBF7594325D41C982947CB /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -357,23 +356,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - D1CBF7594325D41C982947CB /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Theme-ThemeTests/Pods-App-Theme-ThemeTests-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-Theme-ThemeTests/Pods-App-Theme-ThemeTests-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App-Theme-ThemeTests/Pods-App-Theme-ThemeTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; ED83AD5255805030E042D62A /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/WhatsNew/Mockfile b/WhatsNew/Mockfile deleted file mode 100644 index 6107db3ed..000000000 --- a/WhatsNew/Mockfile +++ /dev/null @@ -1,18 +0,0 @@ -sourceryCommand: mint run krzysztofzablocki/Sourcery@2.1.2 sourcery -sourceryTemplate: ../MockTemplate.swifttemplate -unit.tests.mock: - sources: - include: - - ./../WhatsNew - - ./WhatsNew - exclude: [] - output: ./WhatsNewTests/WhatsNewMock.generated.swift - targets: - - MyAppUnitTests - import: - - Core - - WhatsNew - - Foundation - - SwiftUI - - Combine - - OEXFoundation \ No newline at end of file diff --git a/WhatsNew/WhatsNew.xcodeproj/project.pbxproj b/WhatsNew/WhatsNew.xcodeproj/project.pbxproj index 40695e978..893242164 100644 --- a/WhatsNew/WhatsNew.xcodeproj/project.pbxproj +++ b/WhatsNew/WhatsNew.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 020A7B5F2AE131A9000BAF70 /* WhatsNewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020A7B5E2AE131A9000BAF70 /* WhatsNewModel.swift */; }; 020A7B612AE136D2000BAF70 /* WhatsNew.json in Resources */ = {isa = PBXBuildFile; fileRef = 020A7B602AE136D2000BAF70 /* WhatsNew.json */; }; - 020AC2692AEBB69E0086E975 /* WhatsNewMock.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020AC2682AEBB69E0086E975 /* WhatsNewMock.generated.swift */; }; 028A37262ADFF3F8008CA604 /* WhatsNew.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 028A371D2ADFF3F7008CA604 /* WhatsNew.framework */; }; 028A372B2ADFF3F8008CA604 /* WhatsNewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 028A372A2ADFF3F8008CA604 /* WhatsNewTests.swift */; }; 028A373A2ADFF425008CA604 /* Core.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 028A37392ADFF425008CA604 /* Core.framework */; }; @@ -25,6 +24,7 @@ 02EC90AA2AE904E1007DE1E0 /* WhatsNewStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EC90A92AE904E1007DE1E0 /* WhatsNewStorage.swift */; }; 02EC90AC2AE90C64007DE1E0 /* WhatsNewPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EC90AB2AE90C64007DE1E0 /* WhatsNewPage.swift */; }; 14769D3E2B99713800AB36D4 /* WhatsNewAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14769D3D2B99713800AB36D4 /* WhatsNewAnalytics.swift */; }; + A5B468172F29DFCB002A4ECA /* WhatsNewMocks.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B468152F29DFCB002A4ECA /* WhatsNewMocks.generated.swift */; }; B3BB9B06B226989A619C6440 /* Pods_App_WhatsNew.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05AC45C7050E30F8394E0C76 /* Pods_App_WhatsNew.framework */; }; CE7CAF352CC1560900E0AC9D /* OEXFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CE7CAF342CC1560900E0AC9D /* OEXFoundation */; }; CEB1E2672CC14E6400921517 /* OEXFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CEB1E2662CC14E6400921517 /* OEXFoundation */; }; @@ -57,7 +57,6 @@ /* Begin PBXFileReference section */ 020A7B5E2AE131A9000BAF70 /* WhatsNewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhatsNewModel.swift; sourceTree = ""; }; 020A7B602AE136D2000BAF70 /* WhatsNew.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = WhatsNew.json; path = WhatsNew/Data/WhatsNew.json; sourceTree = SOURCE_ROOT; }; - 020AC2682AEBB69E0086E975 /* WhatsNewMock.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WhatsNewMock.generated.swift; path = WhatsNewTests/WhatsNewMock.generated.swift; sourceTree = SOURCE_ROOT; }; 028A371D2ADFF3F7008CA604 /* WhatsNew.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WhatsNew.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 028A37252ADFF3F7008CA604 /* WhatsNewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WhatsNewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 028A372A2ADFF3F8008CA604 /* WhatsNewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhatsNewTests.swift; sourceTree = ""; }; @@ -87,6 +86,7 @@ 9844714991FA40ECDC228CC9 /* Pods-App-WhatsNew.releasedev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-WhatsNew.releasedev.xcconfig"; path = "Target Support Files/Pods-App-WhatsNew/Pods-App-WhatsNew.releasedev.xcconfig"; sourceTree = ""; }; A2CABA11F5E7F89EFD9A05AC /* Pods-App-WhatsNew-WhatsNewTests.debugstage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-WhatsNew-WhatsNewTests.debugstage.xcconfig"; path = "Target Support Files/Pods-App-WhatsNew-WhatsNewTests/Pods-App-WhatsNew-WhatsNewTests.debugstage.xcconfig"; sourceTree = ""; }; A557A3CED4D6327AAE6AA02C /* Pods-App-WhatsNew-WhatsNewTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-WhatsNew-WhatsNewTests.release.xcconfig"; path = "Target Support Files/Pods-App-WhatsNew-WhatsNewTests/Pods-App-WhatsNew-WhatsNewTests.release.xcconfig"; sourceTree = ""; }; + A5B468152F29DFCB002A4ECA /* WhatsNewMocks.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhatsNewMocks.generated.swift; sourceTree = ""; }; A76975E21FF282D59CEC4452 /* Pods-App-WhatsNew.debugprod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-WhatsNew.debugprod.xcconfig"; path = "Target Support Files/Pods-App-WhatsNew/Pods-App-WhatsNew.debugprod.xcconfig"; sourceTree = ""; }; AB8156676C9C771D691ADE07 /* Pods-App-WhatsNew.releaseprod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-WhatsNew.releaseprod.xcconfig"; path = "Target Support Files/Pods-App-WhatsNew/Pods-App-WhatsNew.releaseprod.xcconfig"; sourceTree = ""; }; B7EAC5E8F0ED2F1F81050C30 /* Pods-App-WhatsNew-WhatsNewTests.debugprod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-WhatsNew-WhatsNewTests.debugprod.xcconfig"; path = "Target Support Files/Pods-App-WhatsNew-WhatsNewTests/Pods-App-WhatsNew-WhatsNewTests.debugprod.xcconfig"; sourceTree = ""; }; @@ -165,8 +165,8 @@ 028A37292ADFF3F8008CA604 /* WhatsNewTests */ = { isa = PBXGroup; children = ( + A5B468162F29DFCB002A4ECA /* Generated */, 02EC90B52AE92AEB007DE1E0 /* Presentation */, - 020AC2682AEBB69E0086E975 /* WhatsNewMock.generated.swift */, ); path = WhatsNewTests; sourceTree = ""; @@ -252,6 +252,14 @@ path = ../Pods; sourceTree = ""; }; + A5B468162F29DFCB002A4ECA /* Generated */ = { + isa = PBXGroup; + children = ( + A5B468152F29DFCB002A4ECA /* WhatsNewMocks.generated.swift */, + ); + path = Generated; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -293,7 +301,6 @@ 028A37212ADFF3F7008CA604 /* Sources */, 028A37222ADFF3F7008CA604 /* Frameworks */, 028A37232ADFF3F7008CA604 /* Resources */, - 8A74692D666D8FF13F7BA64F /* [CP] Copy Pods Resources */, CE7CAF372CC1560900E0AC9D /* Embed Frameworks */, ); buildRules = ( @@ -410,23 +417,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 8A74692D666D8FF13F7BA64F /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-WhatsNew-WhatsNewTests/Pods-App-WhatsNew-WhatsNewTests-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-App-WhatsNew-WhatsNewTests/Pods-App-WhatsNew-WhatsNewTests-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App-WhatsNew-WhatsNewTests/Pods-App-WhatsNew-WhatsNewTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; E5055BD989FEEC50EF87C814 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -474,7 +464,7 @@ buildActionMask = 2147483647; files = ( 028A372B2ADFF3F8008CA604 /* WhatsNewTests.swift in Sources */, - 020AC2692AEBB69E0086E975 /* WhatsNewMock.generated.swift in Sources */, + A5B468172F29DFCB002A4ECA /* WhatsNewMocks.generated.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WhatsNew/WhatsNew/Data/WhatsNewStorage.swift b/WhatsNew/WhatsNew/Data/WhatsNewStorage.swift index 57599838e..0646e21a7 100644 --- a/WhatsNew/WhatsNew/Data/WhatsNewStorage.swift +++ b/WhatsNew/WhatsNew/Data/WhatsNewStorage.swift @@ -7,15 +7,14 @@ import Foundation +/// @mockable public protocol WhatsNewStorage: Sendable { var whatsNewVersion: String? {get set} } #if DEBUG -public final class WhatsNewStorageMock: WhatsNewStorage, @unchecked Sendable { - +public final class WhatsNewStoragePreviewMock: WhatsNewStorage, @unchecked Sendable { public var whatsNewVersion: String? - public init() {} } #endif diff --git a/WhatsNew/WhatsNew/Presentation/WhatsNewAnalytics.swift b/WhatsNew/WhatsNew/Presentation/WhatsNewAnalytics.swift index 547afd85c..727445a7f 100644 --- a/WhatsNew/WhatsNew/Presentation/WhatsNewAnalytics.swift +++ b/WhatsNew/WhatsNew/Presentation/WhatsNewAnalytics.swift @@ -7,7 +7,7 @@ import Foundation -//sourcery: AutoMockable +/// @mockable public protocol WhatsNewAnalytics { func whatsnewPopup() func whatsnewDone(totalScreens: Int) @@ -15,9 +15,9 @@ public protocol WhatsNewAnalytics { } #if DEBUG -class WhatsNewAnalyticsMock: WhatsNewAnalytics { - public func whatsnewPopup() {} - public func whatsnewDone(totalScreens: Int) {} - public func whatsnewClose(totalScreens: Int, currentScreen: Int) {} +class WhatsNewAnalyticsPreviewMock: WhatsNewAnalytics { + func whatsnewPopup() {} + func whatsnewDone(totalScreens: Int) {} + func whatsnewClose(totalScreens: Int, currentScreen: Int) {} } #endif diff --git a/WhatsNew/WhatsNew/Presentation/WhatsNewView.swift b/WhatsNew/WhatsNew/Presentation/WhatsNewView.swift index feb9e9877..00cb6a252 100644 --- a/WhatsNew/WhatsNew/Presentation/WhatsNewView.swift +++ b/WhatsNew/WhatsNew/Presentation/WhatsNewView.swift @@ -180,8 +180,8 @@ struct WhatsNewView_Previews: PreviewProvider { WhatsNewView( router: WhatsNewRouterMock(), viewModel: WhatsNewViewModel( - storage: WhatsNewStorageMock(), - analytics: WhatsNewAnalyticsMock() + storage: WhatsNewStoragePreviewMock(), + analytics: WhatsNewAnalyticsPreviewMock() ) ) .loadFonts() diff --git a/WhatsNew/WhatsNewTests/Generated/WhatsNewMocks.generated.swift b/WhatsNew/WhatsNewTests/Generated/WhatsNewMocks.generated.swift new file mode 100644 index 000000000..cc4b643eb --- /dev/null +++ b/WhatsNew/WhatsNewTests/Generated/WhatsNewMocks.generated.swift @@ -0,0 +1,98 @@ +/// +/// @Generated by Mockolo +/// + + + +import Foundation +@testable import WhatsNew + + +public final class WhatsNewAnalyticsMock: WhatsNewAnalytics { + public init() { } + + + public private(set) var whatsnewPopupCallCount = 0 + public var whatsnewPopupHandler: (() -> ())? + public func whatsnewPopup() { + whatsnewPopupCallCount += 1 + if let whatsnewPopupHandler = whatsnewPopupHandler { + whatsnewPopupHandler() + } + + } + + public private(set) var whatsnewDoneCallCount = 0 + public var whatsnewDoneHandler: ((Int) -> ())? + public func whatsnewDone(totalScreens: Int) { + whatsnewDoneCallCount += 1 + if let whatsnewDoneHandler = whatsnewDoneHandler { + whatsnewDoneHandler(totalScreens) + } + + } + + public private(set) var whatsnewCloseCallCount = 0 + public var whatsnewCloseHandler: ((Int, Int) -> ())? + public func whatsnewClose(totalScreens: Int, currentScreen: Int) { + whatsnewCloseCallCount += 1 + if let whatsnewCloseHandler = whatsnewCloseHandler { + whatsnewCloseHandler(totalScreens, currentScreen) + } + + } +} + +public final class WhatsNewStorageMock: WhatsNewStorage, @unchecked Sendable { + public init() { } + public init(whatsNewVersion: String? = nil) { + self.whatsNewVersion = whatsNewVersion + } + + + public private(set) var whatsNewVersionSetCallCount = 0 + public var whatsNewVersion: String? = nil { didSet { whatsNewVersionSetCallCount += 1 } } +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { + print("At \(function), the captured arguments are not Sendable, it is not concurrency-safe.") +} + +fileprivate func warnIfNotSendable(function: String = #function, _: repeat each T) { +} + +/// Will be replaced to `Synchronization.Mutex` in future. +fileprivate final class MockoloMutex: @unchecked Sendable { + private let lock = NSLock() + private var value: Value + init(_ initialValue: Value) { + self.value = initialValue + } +#if compiler(>=6.0) + borrowing func withLock(_ body: (inout sending Value) throws(E) -> Result) throws(E) -> sending Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#else + func withLock(_ body: (inout Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + return try body(&value) + } +#endif +} + +fileprivate struct MockoloUnsafeTransfer: @unchecked Sendable { + var value: Value + init(_ value: Value) { + self.value = value + } +} + +fileprivate struct MockoloHandlerState { + var argValues: [MockoloUnsafeTransfer] = [] + var handler: Handler? = nil + var callCount: Int = 0 +} + diff --git a/WhatsNew/WhatsNewTests/WhatsNewMock.generated.swift b/WhatsNew/WhatsNewTests/WhatsNewMock.generated.swift deleted file mode 100644 index 24726cef8..000000000 --- a/WhatsNew/WhatsNewTests/WhatsNewMock.generated.swift +++ /dev/null @@ -1,227 +0,0 @@ -// Generated using Sourcery 2.1.2 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT - - -// Generated with SwiftyMocky 4.2.0 -// Required Sourcery: 1.8.0 - - -import SwiftyMocky -import XCTest -import Core -import WhatsNew -import Foundation -import SwiftUI -import Combine -import OEXFoundation - - -// MARK: - WhatsNewAnalytics - -open class WhatsNewAnalyticsMock: WhatsNewAnalytics, Mock { - public init(sequencing sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst, stubbing stubbingPolicy: StubbingPolicy = .wrap, file: StaticString = #file, line: UInt = #line) { - SwiftyMockyTestObserver.setup() - self.sequencingPolicy = sequencingPolicy - self.stubbingPolicy = stubbingPolicy - self.file = file - self.line = line - } - - var matcher: Matcher = Matcher.default - var stubbingPolicy: StubbingPolicy = .wrap - var sequencingPolicy: SequencingPolicy = .lastWrittenResolvedFirst - - private var queue = DispatchQueue(label: "com.swiftymocky.invocations", qos: .userInteractive) - private var invocations: [MethodType] = [] - private var methodReturnValues: [Given] = [] - private var methodPerformValues: [Perform] = [] - private var file: StaticString? - private var line: UInt? - - public typealias PropertyStub = Given - public typealias MethodStub = Given - public typealias SubscriptStub = Given - - /// Convenience method - call setupMock() to extend debug information when failure occurs - public func setupMock(file: StaticString = #file, line: UInt = #line) { - self.file = file - self.line = line - } - - /// Clear mock internals. You can specify what to reset (invocations aka verify, givens or performs) or leave it empty to clear all mock internals - public func resetMock(_ scopes: MockScope...) { - let scopes: [MockScope] = scopes.isEmpty ? [.invocation, .given, .perform] : scopes - if scopes.contains(.invocation) { invocations = [] } - if scopes.contains(.given) { methodReturnValues = [] } - if scopes.contains(.perform) { methodPerformValues = [] } - } - - - - - - open func whatsnewPopup() { - addInvocation(.m_whatsnewPopup) - let perform = methodPerformValue(.m_whatsnewPopup) as? () -> Void - perform?() - } - - open func whatsnewDone(totalScreens: Int) { - addInvocation(.m_whatsnewDone__totalScreens_totalScreens(Parameter.value(`totalScreens`))) - let perform = methodPerformValue(.m_whatsnewDone__totalScreens_totalScreens(Parameter.value(`totalScreens`))) as? (Int) -> Void - perform?(`totalScreens`) - } - - open func whatsnewClose(totalScreens: Int, currentScreen: Int) { - addInvocation(.m_whatsnewClose__totalScreens_totalScreenscurrentScreen_currentScreen(Parameter.value(`totalScreens`), Parameter.value(`currentScreen`))) - let perform = methodPerformValue(.m_whatsnewClose__totalScreens_totalScreenscurrentScreen_currentScreen(Parameter.value(`totalScreens`), Parameter.value(`currentScreen`))) as? (Int, Int) -> Void - perform?(`totalScreens`, `currentScreen`) - } - - - fileprivate enum MethodType { - case m_whatsnewPopup - case m_whatsnewDone__totalScreens_totalScreens(Parameter) - case m_whatsnewClose__totalScreens_totalScreenscurrentScreen_currentScreen(Parameter, Parameter) - - static func compareParameters(lhs: MethodType, rhs: MethodType, matcher: Matcher) -> Matcher.ComparisonResult { - switch (lhs, rhs) { - case (.m_whatsnewPopup, .m_whatsnewPopup): return .match - - case (.m_whatsnewDone__totalScreens_totalScreens(let lhsTotalscreens), .m_whatsnewDone__totalScreens_totalScreens(let rhsTotalscreens)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTotalscreens, rhs: rhsTotalscreens, with: matcher), lhsTotalscreens, rhsTotalscreens, "totalScreens")) - return Matcher.ComparisonResult(results) - - case (.m_whatsnewClose__totalScreens_totalScreenscurrentScreen_currentScreen(let lhsTotalscreens, let lhsCurrentscreen), .m_whatsnewClose__totalScreens_totalScreenscurrentScreen_currentScreen(let rhsTotalscreens, let rhsCurrentscreen)): - var results: [Matcher.ParameterComparisonResult] = [] - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsTotalscreens, rhs: rhsTotalscreens, with: matcher), lhsTotalscreens, rhsTotalscreens, "totalScreens")) - results.append(Matcher.ParameterComparisonResult(Parameter.compare(lhs: lhsCurrentscreen, rhs: rhsCurrentscreen, with: matcher), lhsCurrentscreen, rhsCurrentscreen, "currentScreen")) - return Matcher.ComparisonResult(results) - default: return .none - } - } - - func intValue() -> Int { - switch self { - case .m_whatsnewPopup: return 0 - case let .m_whatsnewDone__totalScreens_totalScreens(p0): return p0.intValue - case let .m_whatsnewClose__totalScreens_totalScreenscurrentScreen_currentScreen(p0, p1): return p0.intValue + p1.intValue - } - } - func assertionName() -> String { - switch self { - case .m_whatsnewPopup: return ".whatsnewPopup()" - case .m_whatsnewDone__totalScreens_totalScreens: return ".whatsnewDone(totalScreens:)" - case .m_whatsnewClose__totalScreens_totalScreenscurrentScreen_currentScreen: return ".whatsnewClose(totalScreens:currentScreen:)" - } - } - } - - open class Given: StubbedMethod { - fileprivate var method: MethodType - - private init(method: MethodType, products: [StubProduct]) { - self.method = method - super.init(products) - } - - - } - - public struct Verify { - fileprivate var method: MethodType - - public static func whatsnewPopup() -> Verify { return Verify(method: .m_whatsnewPopup)} - public static func whatsnewDone(totalScreens: Parameter) -> Verify { return Verify(method: .m_whatsnewDone__totalScreens_totalScreens(`totalScreens`))} - public static func whatsnewClose(totalScreens: Parameter, currentScreen: Parameter) -> Verify { return Verify(method: .m_whatsnewClose__totalScreens_totalScreenscurrentScreen_currentScreen(`totalScreens`, `currentScreen`))} - } - - public struct Perform { - fileprivate var method: MethodType - var performs: Any - - public static func whatsnewPopup(perform: @escaping () -> Void) -> Perform { - return Perform(method: .m_whatsnewPopup, performs: perform) - } - public static func whatsnewDone(totalScreens: Parameter, perform: @escaping (Int) -> Void) -> Perform { - return Perform(method: .m_whatsnewDone__totalScreens_totalScreens(`totalScreens`), performs: perform) - } - public static func whatsnewClose(totalScreens: Parameter, currentScreen: Parameter, perform: @escaping (Int, Int) -> Void) -> Perform { - return Perform(method: .m_whatsnewClose__totalScreens_totalScreenscurrentScreen_currentScreen(`totalScreens`, `currentScreen`), performs: perform) - } - } - - public func given(_ method: Given) { - methodReturnValues.append(method) - } - - public func perform(_ method: Perform) { - methodPerformValues.append(method) - methodPerformValues.sort { $0.method.intValue() < $1.method.intValue() } - } - - public func verify(_ method: Verify, count: Count = Count.moreOrEqual(to: 1), file: StaticString = #file, line: UInt = #line) { - let fullMatches = matchingCalls(method, file: file, line: line) - let success = count.matches(fullMatches) - let assertionName = method.method.assertionName() - let feedback: String = { - guard !success else { return "" } - return Utils.closestCallsMessage( - for: self.invocations.map { invocation in - matcher.set(file: file, line: line) - defer { matcher.clearFileAndLine() } - return MethodType.compareParameters(lhs: invocation, rhs: method.method, matcher: matcher) - }, - name: assertionName - ) - }() - MockyAssert(success, "Expected: \(count) invocations of `\(assertionName)`, but was: \(fullMatches).\(feedback)", file: file, line: line) - } - - private func addInvocation(_ call: MethodType) { - self.queue.sync { invocations.append(call) } - } - private func methodReturnValue(_ method: MethodType) throws -> StubProduct { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let candidates = sequencingPolicy.sorted(methodReturnValues, by: { $0.method.intValue() > $1.method.intValue() }) - let matched = candidates.first(where: { $0.isValid && MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch }) - guard let product = matched?.getProduct(policy: self.stubbingPolicy) else { throw MockError.notStubed } - return product - } - private func methodPerformValue(_ method: MethodType) -> Any? { - matcher.set(file: self.file, line: self.line) - defer { matcher.clearFileAndLine() } - let matched = methodPerformValues.reversed().first { MethodType.compareParameters(lhs: $0.method, rhs: method, matcher: matcher).isFullMatch } - return matched?.performs - } - private func matchingCalls(_ method: MethodType, file: StaticString?, line: UInt?) -> [MethodType] { - matcher.set(file: file ?? self.file, line: line ?? self.line) - defer { matcher.clearFileAndLine() } - return invocations.filter { MethodType.compareParameters(lhs: $0, rhs: method, matcher: matcher).isFullMatch } - } - private func matchingCalls(_ method: Verify, file: StaticString?, line: UInt?) -> Int { - return matchingCalls(method.method, file: file, line: line).count - } - private func givenGetterValue(_ method: MethodType, _ message: String) -> T { - do { - return try methodReturnValue(method).casted() - } catch { - onFatalFailure(message) - Failure(message) - } - } - private func optionalGivenGetterValue(_ method: MethodType, _ message: String) -> T? { - do { - return try methodReturnValue(method).casted() - } catch { - return nil - } - } - private func onFatalFailure(_ message: String) { - guard let file = self.file, let line = self.line else { return } // Let if fail if cannot handle gratefully - SwiftyMockyTestObserver.handleFatalError(message: message, file: file, line: line) - } -} - diff --git a/generateAllMocks.sh b/generateAllMocks.sh deleted file mode 100755 index f532b0696..000000000 --- a/generateAllMocks.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -cd "${DIR}" -cd ./Core -./../Pods/SwiftyMocky/bin/swiftymocky generate -cd ../Authorization -./../Pods/SwiftyMocky/bin/swiftymocky generate -cd ../Course -./../Pods/SwiftyMocky/bin/swiftymocky generate -cd ../Dashboard -./../Pods/SwiftyMocky/bin/swiftymocky generate -cd ../Discovery -./../Pods/SwiftyMocky/bin/swiftymocky generate -cd ../Discussion -./../Pods/SwiftyMocky/bin/swiftymocky generate -cd ../Downloads -./../Pods/SwiftyMocky/bin/swiftymocky generate -cd ../Profile -./../Pods/SwiftyMocky/bin/swiftymocky generate -cd ../WhatsNew -./../Pods/SwiftyMocky/bin/swiftymocky generate -cd ../AppDates -./../Pods/SwiftyMocky/bin/swiftymocky generate diff --git a/generateMockoloMocks.sh b/generateMockoloMocks.sh new file mode 100755 index 000000000..62b717bf4 --- /dev/null +++ b/generateMockoloMocks.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +# Script to generate mocks using Mockolo +# Usage: ./generateMockoloMocks.sh + +set -e + +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +cd "${DIR}" + +# Check if mockolo is installed +if ! which mockolo >/dev/null; then + echo "Error: mockolo is not installed" + echo "Install it with: brew install mockolo" + exit 1 +fi + +echo "Generating mocks with Mockolo..." + +# Core module +echo "Generating Core mocks..." +mockolo \ + --sourcedirs "Core/Core" \ + --destination "Core/CoreTests/Generated/CoreMocks.generated.swift" \ + --mock-final \ + --testable-imports "Core" \ + --custom-imports "Foundation" "SwiftUI" "Combine" "OEXFoundation" "Alamofire" "CoreData" "ZipArchive" + +# Authorization module (includes Core sources for shared protocols like AuthInteractorProtocol) +echo "Generating Authorization mocks..." +mockolo \ + --sourcedirs "Authorization/Authorization" "Core/Core" \ + --destination "Authorization/AuthorizationTests/Generated/AuthorizationMocks.generated.swift" \ + --mock-final \ + --testable-imports "Authorization" "Core" \ + --custom-imports "Foundation" "SwiftUI" "Combine" "OEXFoundation" "Alamofire" "CoreData" + +# Course module (includes Core sources for shared protocols) +echo "Generating Course mocks..." +mockolo \ + --sourcedirs "Course/Course" "Core/Core" \ + --destination "Course/CourseTests/Generated/CourseMocks.generated.swift" \ + --mock-final \ + --testable-imports "Course" "Core" \ + --custom-imports "Foundation" "SwiftUI" "Combine" "OEXFoundation" "Alamofire" "CoreData" + +# WhatsNew module +echo "Generating WhatsNew mocks..." +mockolo \ + --sourcedirs "WhatsNew/WhatsNew" \ + --destination "WhatsNew/WhatsNewTests/Generated/WhatsNewMocks.generated.swift" \ + --mock-final \ + --testable-imports "WhatsNew" \ + --custom-imports "Foundation" + +# Discovery module (includes Core sources for shared protocols) +echo "Generating Discovery mocks..." +mockolo \ + --sourcedirs "Discovery/Discovery" "Core/Core" \ + --destination "Discovery/DiscoveryTests/Generated/DiscoveryMocks.generated.swift" \ + --mock-final \ + --testable-imports "Discovery" "Core" \ + --custom-imports "Foundation" "SwiftUI" "Combine" "OEXFoundation" "Alamofire" "CoreData" + +# Dashboard module (includes Core sources for shared protocols) +echo "Generating Dashboard mocks..." +mockolo \ + --sourcedirs "Dashboard/Dashboard" "Core/Core" \ + --destination "Dashboard/DashboardTests/Generated/DashboardMocks.generated.swift" \ + --mock-final \ + --testable-imports "Dashboard" "Core" \ + --custom-imports "Foundation" "SwiftUI" "Combine" "OEXFoundation" + +# Downloads module (includes Core sources for shared protocols) +echo "Generating Downloads mocks..." +mockolo \ + --sourcedirs "Downloads/Downloads" "Core/Core" \ + --destination "Downloads/DownloadsTests/Generated/DownloadsMocks.generated.swift" \ + --mock-final \ + --testable-imports "Downloads" "Core" \ + --custom-imports "Foundation" "SwiftUI" "Combine" "OEXFoundation" + +# Profile module (includes Core sources for shared protocols) +echo "Generating Profile mocks..." +mockolo \ + --sourcedirs "Profile/Profile" "Core/Core" \ + --destination "Profile/ProfileTests/Generated/ProfileMocks.generated.swift" \ + --mock-final \ + --testable-imports "Profile" "Core" \ + --custom-imports "Foundation" "SwiftUI" "Combine" "OEXFoundation" "Alamofire" + +# Discussion module (includes Core sources for shared protocols) +echo "Generating Discussion mocks..." +mockolo \ + --sourcedirs "Discussion/Discussion" "Core/Core" \ + --destination "Discussion/DiscussionTests/Generated/DiscussionMocks.generated.swift" \ + --mock-final \ + --testable-imports "Discussion" "Core" \ + --custom-imports "Foundation" "SwiftUI" "Combine" "OEXFoundation" "Alamofire" + +# AppDates module (includes Core sources for shared protocols) +echo "Generating AppDates mocks..." +mockolo \ + --sourcedirs "AppDates/AppDates" "Core/Core" \ + --destination "AppDates/AppDatesTests/Generated/AppDatesMocks.generated.swift" \ + --mock-final \ + --testable-imports "AppDates" "Core" \ + --custom-imports "Foundation" "SwiftUI" "Combine" "OEXFoundation" + +echo "Done! All mocks generated successfully."