├── .gitignore ├── .travis.yml ├── App.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── App.xcscheme ├── App.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── App ├── Application │ ├── AppAppearance.swift │ ├── AppConfigurations.swift │ ├── AppDelegate.swift │ ├── AppFlowCoordinator.swift │ └── DIContainer │ │ └── AppDIContainer.swift └── Resources │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── Info.plist │ ├── en.lproj │ └── Localizable.strings │ └── es.lproj │ ├── LaunchScreen.strings │ └── Localizable.strings ├── AppUITests ├── Info.plist └── Presentation │ └── MoviesScene │ └── MoviesSceneUITests.swift ├── DevPods ├── Authentication │ ├── Authentication.podspec │ ├── Authentication │ │ └── Module │ │ │ └── AuthNetworkSessionManager.swift │ ├── Example │ │ ├── Authentication.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── Authentication-Example.xcscheme │ │ └── Authentication │ │ │ ├── AppDelegate.swift │ │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.xib │ │ │ └── Main.storyboard │ │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ └── ViewController.swift │ ├── LICENSE │ └── README.md ├── MoviesSearch │ ├── Example │ │ ├── MoviesSearch.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── MoviesSearch-Example.xcscheme │ │ └── MoviesSearch │ │ │ ├── AppDelegate.swift │ │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.xib │ │ │ └── Main.storyboard │ │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ └── ViewController.swift │ ├── LICENSE │ ├── MoviesSearch.podspec │ ├── MoviesSearch │ │ ├── Module │ │ │ ├── Assets │ │ │ │ └── Assets.xcassets │ │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ └── Contents.json │ │ │ │ │ └── Contents.json │ │ │ ├── Common │ │ │ │ ├── Bundle+Resource.swift │ │ │ │ ├── Cancelable.swift │ │ │ │ └── ConnectionError.swift │ │ │ ├── DIContainer.swift │ │ │ ├── Data │ │ │ │ ├── Network │ │ │ │ │ ├── APIEndpoints.swift │ │ │ │ │ └── DataMapping │ │ │ │ │ │ ├── MoviesRequestDTO+Mapping.swift │ │ │ │ │ │ └── MoviesResponseDTO+Mapping.swift │ │ │ │ ├── PersistentStorages │ │ │ │ │ ├── CoreDataStorage │ │ │ │ │ │ ├── CoreDataStorage.swift │ │ │ │ │ │ └── CoreDataStorage.xcdatamodeld │ │ │ │ │ │ │ ├── .xccurrentversion │ │ │ │ │ │ │ ├── CoreDataStorage 2.xcdatamodel │ │ │ │ │ │ │ └── contents │ │ │ │ │ │ │ └── CoreDataStorage.xcdatamodel │ │ │ │ │ │ │ └── contents │ │ │ │ │ ├── MoviesQueriesStorage │ │ │ │ │ │ ├── CoreDataStorage │ │ │ │ │ │ │ ├── CoreDataMoviesQueriesStorage.swift │ │ │ │ │ │ │ └── EntityMapping │ │ │ │ │ │ │ │ └── MovieQueryEntity+Mapping.swift │ │ │ │ │ │ ├── MoviesQueriesStorage.swift │ │ │ │ │ │ └── UserDefaultsStorage │ │ │ │ │ │ │ ├── DataMapping │ │ │ │ │ │ │ └── MovieQueryUDS+Mapping.swift │ │ │ │ │ │ │ └── UserDefaultsMoviesQueriesStorage.swift │ │ │ │ │ └── MoviesResponseStorage │ │ │ │ │ │ ├── CoreDataMoviesResponseStorage.swift │ │ │ │ │ │ ├── EntityMapping │ │ │ │ │ │ └── MoviesResponseEntity+Mapping.swift │ │ │ │ │ │ └── MoviesResponseStorage.swift │ │ │ │ └── Repositories │ │ │ │ │ ├── DefaultMoviesQueriesRepository.swift │ │ │ │ │ ├── DefaultMoviesRepository.swift │ │ │ │ │ ├── DefaultPosterImagesRepository.swift │ │ │ │ │ └── Utils │ │ │ │ │ └── RepositoryTask.swift │ │ │ ├── Domain │ │ │ │ ├── Entities │ │ │ │ │ ├── Movie.swift │ │ │ │ │ └── MovieQuery.swift │ │ │ │ ├── Interfaces │ │ │ │ │ └── Repositories │ │ │ │ │ │ ├── MoviesQueriesRepository.swift │ │ │ │ │ │ ├── MoviesRepository.swift │ │ │ │ │ │ └── PosterImagesRepository.swift │ │ │ │ └── UseCases │ │ │ │ │ ├── FetchRecentMovieQueriesUseCase.swift │ │ │ │ │ └── SearchMoviesUseCase.swift │ │ │ ├── Module.swift │ │ │ └── Presentation │ │ │ │ ├── MoviesScene │ │ │ │ ├── Behaviors │ │ │ │ │ ├── BackButtonEmptyTitleNavigationBarBehavior.swift │ │ │ │ │ └── BlackStyleNavigationBarBehavior.swift │ │ │ │ ├── Flows │ │ │ │ │ └── MoviesSearchFlowCoordinator.swift │ │ │ │ ├── MovieDetails │ │ │ │ │ ├── View │ │ │ │ │ │ ├── MovieDetailsViewController.storyboard │ │ │ │ │ │ └── MovieDetailsViewController.swift │ │ │ │ │ └── ViewModel │ │ │ │ │ │ └── MovieDetailsViewModel.swift │ │ │ │ ├── MoviesList │ │ │ │ │ ├── View │ │ │ │ │ │ ├── MoviesListTableView │ │ │ │ │ │ │ ├── Cells │ │ │ │ │ │ │ │ └── MoviesListItemCell.swift │ │ │ │ │ │ │ └── MoviesListTableViewController.swift │ │ │ │ │ │ ├── MoviesListViewController.storyboard │ │ │ │ │ │ └── MoviesListViewController.swift │ │ │ │ │ └── ViewModel │ │ │ │ │ │ ├── MoviesListItemViewModel.swift │ │ │ │ │ │ └── MoviesListViewModel.swift │ │ │ │ └── MoviesQueriesList │ │ │ │ │ ├── View │ │ │ │ │ ├── SwiftUI │ │ │ │ │ │ └── MoviesQueryListView.swift │ │ │ │ │ └── UIKit │ │ │ │ │ │ ├── Cells │ │ │ │ │ │ └── MoviesQueriesItemCell.swift │ │ │ │ │ │ ├── MoviesQueriesTableViewController.storyboard │ │ │ │ │ │ └── MoviesQueriesTableViewController.swift │ │ │ │ │ └── ViewModel │ │ │ │ │ ├── MoviesQueryListItemViewModel.swift │ │ │ │ │ └── MoviesQueryListViewModel.swift │ │ │ │ └── Utils │ │ │ │ ├── AccessibilityIdentifier.swift │ │ │ │ ├── Extensions │ │ │ │ ├── CGSize+ScaledSize.swift │ │ │ │ ├── DataTransferError+ConnectionError.swift │ │ │ │ ├── UIImageView+ImageSizeAfterAspectFit.swift │ │ │ │ ├── UIViewController+ActivityIndicator.swift │ │ │ │ ├── UIViewController+AddBehaviors.swift │ │ │ │ └── UIViewController+AddChild.swift │ │ │ │ ├── LiteralBundleImage.swift │ │ │ │ ├── LoadingView.swift │ │ │ │ ├── Observable.swift │ │ │ │ └── Protocols │ │ │ │ ├── Alertable.swift │ │ │ │ └── StoryboardInstantiable.swift │ │ └── Tests │ │ │ ├── Domain │ │ │ └── UseCases │ │ │ │ └── SearchMoviesUseCaseTests.swift │ │ │ ├── Mocks │ │ │ └── Movie+Stub.swift │ │ │ └── Presentation │ │ │ └── MoviesScene │ │ │ ├── Mocks │ │ │ └── PosterImagesRepositoryMock.swift │ │ │ ├── MovieDetailsViewModelTests.swift │ │ │ ├── MoviesListViewModelSpec.swift │ │ │ ├── MoviesListViewTests.swift │ │ │ └── MoviesQueriesListViewModelTests.swift │ └── README.md └── Networking │ ├── Example │ ├── Networking.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Networking-Example.xcscheme │ └── Networking │ │ ├── AppDelegate.swift │ │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── ViewController.swift │ ├── LICENSE │ ├── Networking.podspec │ ├── Networking │ ├── Module │ │ ├── DataTransferService.swift │ │ ├── Endpoint.swift │ │ ├── NetworkConfig.swift │ │ └── NetworkService.swift │ └── Tests │ │ ├── DataTransferServiceTests.swift │ │ ├── Mocks │ │ ├── NetworkConfigurableMock.swift │ │ └── NetworkSessionManagerMock.swift │ │ └── NetworkServiceTests.swift │ └── README.md ├── Gemfile ├── Gemfile.lock ├── Podfile ├── Podfile.lock ├── Pods ├── Alamofire │ ├── LICENSE │ ├── README.md │ └── Source │ │ ├── AFError.swift │ │ ├── Alamofire.swift │ │ ├── DispatchQueue+Alamofire.swift │ │ ├── MultipartFormData.swift │ │ ├── NetworkReachabilityManager.swift │ │ ├── Notifications.swift │ │ ├── ParameterEncoding.swift │ │ ├── Request.swift │ │ ├── Response.swift │ │ ├── ResponseSerialization.swift │ │ ├── Result.swift │ │ ├── ServerTrustPolicy.swift │ │ ├── SessionDelegate.swift │ │ ├── SessionManager.swift │ │ ├── TaskDelegate.swift │ │ ├── Timeline.swift │ │ └── Validation.swift ├── Local Podspecs │ ├── Authentication.podspec.json │ ├── MoviesSearch.podspec.json │ └── Networking.podspec.json ├── Manifest.lock ├── Nimble │ ├── Carthage │ │ └── Checkouts │ │ │ ├── CwlCatchException │ │ │ └── Sources │ │ │ │ ├── CwlCatchException │ │ │ │ └── CwlCatchException.swift │ │ │ │ └── CwlCatchExceptionSupport │ │ │ │ ├── CwlCatchException.m │ │ │ │ └── include │ │ │ │ └── CwlCatchException.h │ │ │ └── CwlPreconditionTesting │ │ │ └── Sources │ │ │ ├── CwlMachBadInstructionHandler │ │ │ ├── CwlMachBadInstructionHandler.m │ │ │ ├── include │ │ │ │ └── CwlMachBadInstructionHandler.h │ │ │ ├── mach_excServer.c │ │ │ └── mach_excServer.h │ │ │ └── CwlPreconditionTesting │ │ │ ├── CwlBadInstructionException.swift │ │ │ ├── CwlCatchBadInstruction.swift │ │ │ └── CwlDarwinDefinitions.swift │ ├── LICENSE │ ├── README.md │ └── Sources │ │ ├── Nimble │ │ ├── Adapters │ │ │ ├── AdapterProtocols.swift │ │ │ ├── AssertionDispatcher.swift │ │ │ ├── AssertionRecorder.swift │ │ │ ├── NMBExpectation.swift │ │ │ ├── NMBObjCMatcher.swift │ │ │ ├── NimbleEnvironment.swift │ │ │ └── NimbleXCTestHandler.swift │ │ ├── DSL+Wait.swift │ │ ├── DSL.swift │ │ ├── Expectation.swift │ │ ├── ExpectationMessage.swift │ │ ├── Expression.swift │ │ ├── FailureMessage.swift │ │ ├── Matchers │ │ │ ├── AllPass.swift │ │ │ ├── Async.swift │ │ │ ├── BeAKindOf.swift │ │ │ ├── BeAnInstanceOf.swift │ │ │ ├── BeCloseTo.swift │ │ │ ├── BeEmpty.swift │ │ │ ├── BeGreaterThan.swift │ │ │ ├── BeGreaterThanOrEqualTo.swift │ │ │ ├── BeIdenticalTo.swift │ │ │ ├── BeLessThan.swift │ │ │ ├── BeLessThanOrEqual.swift │ │ │ ├── BeLogical.swift │ │ │ ├── BeNil.swift │ │ │ ├── BeVoid.swift │ │ │ ├── BeginWith.swift │ │ │ ├── BeginWithPrefix.swift │ │ │ ├── Contain.swift │ │ │ ├── ContainElementSatisfying.swift │ │ │ ├── ElementsEqual.swift │ │ │ ├── EndWith.swift │ │ │ ├── Equal+Tuple.swift │ │ │ ├── Equal.swift │ │ │ ├── HaveCount.swift │ │ │ ├── Match.swift │ │ │ ├── MatchError.swift │ │ │ ├── MatcherFunc.swift │ │ │ ├── MatcherProtocols.swift │ │ │ ├── PostNotification.swift │ │ │ ├── Predicate.swift │ │ │ ├── RaisesException.swift │ │ │ ├── SatisfyAllOf.swift │ │ │ ├── SatisfyAnyOf.swift │ │ │ ├── ThrowAssertion.swift │ │ │ ├── ThrowError.swift │ │ │ └── ToSucceed.swift │ │ ├── Nimble.h │ │ └── Utils │ │ │ ├── Await.swift │ │ │ ├── DispatchTimeInterval.swift │ │ │ ├── Errors.swift │ │ │ ├── SourceLocation.swift │ │ │ └── Stringers.swift │ │ └── NimbleObjectiveC │ │ ├── DSL.h │ │ ├── DSL.m │ │ ├── NMBExceptionCapture.h │ │ ├── NMBExceptionCapture.m │ │ ├── NMBStringify.h │ │ ├── NMBStringify.m │ │ └── XCTestObservationCenter+Register.m ├── Pods.xcodeproj │ └── project.pbxproj ├── Quick │ ├── LICENSE │ ├── README.md │ └── Sources │ │ ├── Quick │ │ ├── Behavior.swift │ │ ├── Callsite.swift │ │ ├── Configuration │ │ │ ├── Configuration.swift │ │ │ └── QuickConfiguration.swift │ │ ├── DSL │ │ │ ├── DSL.swift │ │ │ └── World+DSL.swift │ │ ├── ErrorUtility.swift │ │ ├── Example.swift │ │ ├── ExampleGroup.swift │ │ ├── ExampleMetadata.swift │ │ ├── Filter.swift │ │ ├── Hooks │ │ │ ├── Closures.swift │ │ │ ├── ExampleHooks.swift │ │ │ ├── HooksPhase.swift │ │ │ └── SuiteHooks.swift │ │ ├── NSBundle+CurrentTestBundle.swift │ │ ├── QuickSelectedTestSuiteBuilder.swift │ │ ├── QuickTestObservation.swift │ │ ├── QuickTestSuite.swift │ │ ├── String+C99ExtendedIdentifier.swift │ │ ├── URL+FileName.swift │ │ └── World.swift │ │ ├── QuickObjCRuntime │ │ ├── QuickSpecBase.m │ │ └── include │ │ │ ├── QuickObjCRuntime.h │ │ │ └── QuickSpecBase.h │ │ └── QuickObjectiveC │ │ ├── Configuration │ │ ├── QuickConfiguration.h │ │ └── QuickConfiguration.m │ │ ├── DSL │ │ ├── QCKDSL.h │ │ └── QCKDSL.m │ │ ├── Quick.h │ │ ├── QuickSpec.h │ │ ├── QuickSpec.m │ │ └── XCTestSuite+QuickTestSuiteBuilder.m ├── Target Support Files │ ├── Alamofire │ │ ├── Alamofire-Info.plist │ │ ├── Alamofire-dummy.m │ │ ├── Alamofire-prefix.pch │ │ ├── Alamofire-umbrella.h │ │ ├── Alamofire.modulemap │ │ └── Alamofire.xcconfig │ ├── Authentication │ │ ├── Authentication-Info.plist │ │ ├── Authentication-dummy.m │ │ ├── Authentication-prefix.pch │ │ ├── Authentication-umbrella.h │ │ ├── Authentication.modulemap │ │ └── Authentication.xcconfig │ ├── MoviesSearch │ │ ├── MoviesSearch-Info.plist │ │ ├── MoviesSearch-Unit-Tests-Info.plist │ │ ├── MoviesSearch-Unit-Tests-frameworks.sh │ │ ├── MoviesSearch-Unit-Tests-prefix.pch │ │ ├── MoviesSearch-Unit-Tests-resources.sh │ │ ├── MoviesSearch-dummy.m │ │ ├── MoviesSearch-prefix.pch │ │ ├── MoviesSearch-umbrella.h │ │ ├── MoviesSearch.modulemap │ │ ├── MoviesSearch.unit-tests.xcconfig │ │ └── MoviesSearch.xcconfig │ ├── Networking │ │ ├── Networking-Info.plist │ │ ├── Networking-Unit-Tests-Info.plist │ │ ├── Networking-Unit-Tests-frameworks.sh │ │ ├── Networking-Unit-Tests-prefix.pch │ │ ├── Networking-dummy.m │ │ ├── Networking-prefix.pch │ │ ├── Networking-umbrella.h │ │ ├── Networking.modulemap │ │ ├── Networking.unit-tests.xcconfig │ │ └── Networking.xcconfig │ ├── Nimble │ │ ├── Nimble-Info.plist │ │ ├── Nimble-dummy.m │ │ ├── Nimble-prefix.pch │ │ ├── Nimble-umbrella.h │ │ ├── Nimble.modulemap │ │ └── Nimble.xcconfig │ ├── Pods-App │ │ ├── Pods-App-Info.plist │ │ ├── Pods-App-acknowledgements.markdown │ │ ├── Pods-App-acknowledgements.plist │ │ ├── Pods-App-dummy.m │ │ ├── Pods-App-frameworks.sh │ │ ├── Pods-App-resources.sh │ │ ├── Pods-App-umbrella.h │ │ ├── Pods-App.debug.xcconfig │ │ ├── Pods-App.modulemap │ │ └── Pods-App.release.xcconfig │ ├── Pods-AppUITests │ │ ├── Pods-AppUITests-Info.plist │ │ ├── Pods-AppUITests-acknowledgements.markdown │ │ ├── Pods-AppUITests-acknowledgements.plist │ │ ├── Pods-AppUITests-dummy.m │ │ ├── Pods-AppUITests-frameworks.sh │ │ ├── Pods-AppUITests-resources.sh │ │ ├── Pods-AppUITests-umbrella.h │ │ ├── Pods-AppUITests.debug.xcconfig │ │ ├── Pods-AppUITests.modulemap │ │ └── Pods-AppUITests.release.xcconfig │ ├── Pods-Authentication_Example │ │ ├── Pods-Authentication_Example-Info.plist │ │ ├── Pods-Authentication_Example-acknowledgements.markdown │ │ ├── Pods-Authentication_Example-acknowledgements.plist │ │ ├── Pods-Authentication_Example-dummy.m │ │ ├── Pods-Authentication_Example-frameworks.sh │ │ ├── Pods-Authentication_Example-umbrella.h │ │ ├── Pods-Authentication_Example.debug.xcconfig │ │ ├── Pods-Authentication_Example.modulemap │ │ └── Pods-Authentication_Example.release.xcconfig │ ├── Pods-MoviesSearch_Example │ │ ├── Pods-MoviesSearch_Example-Info.plist │ │ ├── Pods-MoviesSearch_Example-acknowledgements.markdown │ │ ├── Pods-MoviesSearch_Example-acknowledgements.plist │ │ ├── Pods-MoviesSearch_Example-dummy.m │ │ ├── Pods-MoviesSearch_Example-frameworks.sh │ │ ├── Pods-MoviesSearch_Example-resources.sh │ │ ├── Pods-MoviesSearch_Example-umbrella.h │ │ ├── Pods-MoviesSearch_Example.debug.xcconfig │ │ ├── Pods-MoviesSearch_Example.modulemap │ │ └── Pods-MoviesSearch_Example.release.xcconfig │ ├── Pods-Networking_Example │ │ ├── Pods-Networking_Example-Info.plist │ │ ├── Pods-Networking_Example-acknowledgements.markdown │ │ ├── Pods-Networking_Example-acknowledgements.plist │ │ ├── Pods-Networking_Example-dummy.m │ │ ├── Pods-Networking_Example-frameworks.sh │ │ ├── Pods-Networking_Example-umbrella.h │ │ ├── Pods-Networking_Example.debug.xcconfig │ │ ├── Pods-Networking_Example.modulemap │ │ └── Pods-Networking_Example.release.xcconfig │ ├── Quick │ │ ├── Quick-Info.plist │ │ ├── Quick-dummy.m │ │ ├── Quick-prefix.pch │ │ ├── Quick-umbrella.h │ │ ├── Quick.modulemap │ │ └── Quick.xcconfig │ └── iOSSnapshotTestCase │ │ ├── iOSSnapshotTestCase-Info.plist │ │ ├── iOSSnapshotTestCase-dummy.m │ │ ├── iOSSnapshotTestCase-prefix.pch │ │ ├── iOSSnapshotTestCase-umbrella.h │ │ ├── iOSSnapshotTestCase.modulemap │ │ └── iOSSnapshotTestCase.xcconfig └── iOSSnapshotTestCase │ ├── LICENSE │ ├── README.md │ └── src │ ├── iOSSnapshotTestCase │ └── SwiftSupport.swift │ └── iOSSnapshotTestCaseCore │ ├── Categories │ ├── UIApplication+KeyWindow.h │ ├── UIApplication+KeyWindow.m │ ├── UIImage+Compare.h │ ├── UIImage+Compare.m │ ├── UIImage+Diff.h │ ├── UIImage+Diff.m │ ├── UIImage+Snapshot.h │ └── UIImage+Snapshot.m │ ├── FBSnapshotTestCase.m │ ├── FBSnapshotTestCasePlatform.m │ ├── FBSnapshotTestController.m │ └── Public │ ├── FBSnapshotTestCase.h │ ├── FBSnapshotTestCasePlatform.h │ └── FBSnapshotTestController.h ├── README.md ├── README_FILES ├── ModulesDependencies.png ├── ModulesDependenciesAuth.jpg ├── ModulesScaled.jpeg ├── VideoPart1Preview.png └── VideoPart2Preview.png ├── SnapshotTests ├── FailureDiffs │ └── MoviesSearch_Unit_Tests.MoviesListViewTests │ │ ├── diff_test_whenHasItems_thenShowItemsOnScreen@3x.png │ │ ├── diff_test_whenViewIsEmpty_thenShowEmptyScreen@3x.png │ │ ├── failed_test_whenHasItems_thenShowItemsOnScreen@3x.png │ │ ├── failed_test_whenViewIsEmpty_thenShowEmptyScreen@3x.png │ │ ├── reference_test_whenHasItems_thenShowItemsOnScreen@3x.png │ │ └── reference_test_whenViewIsEmpty_thenShowEmptyScreen@3x.png └── ReferenceImages_64 │ └── MoviesSearch_Unit_Tests.MoviesListViewTests │ ├── test_whenHasItems_thenShowItemsOnScreen@2x.png │ ├── test_whenHasItems_thenShowItemsOnScreen@3x.png │ ├── test_whenViewIsEmpty_thenShowEmptyScreen@2x.png │ └── test_whenViewIsEmpty_thenShowEmptyScreen@3x.png └── fastlane ├── Appfile ├── Fastfile ├── README.md ├── report.xml └── test_output ├── report.html └── report.junit /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS X 2 | *.DS_Store 3 | 4 | # Xcode 5 | *.xcuserstate 6 | project.xcworkspace/ 7 | xcuserdata/ 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: osx 2 | osx_image: xcode12 3 | language: swift 4 | script: 5 | - fastlane test 6 | -------------------------------------------------------------------------------- /App.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /App.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /App/Application/AppAppearance.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppAppearance.swift 3 | // App 4 | // 5 | // Created by Oleh on 23.09.18. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | final class AppAppearance { 12 | 13 | static func setupAppearance() { 14 | if #available(iOS 15, *) { 15 | let appearance = UINavigationBarAppearance() 16 | appearance.configureWithOpaqueBackground() 17 | appearance.titleTextAttributes = [.foregroundColor: UIColor.white] 18 | appearance.backgroundColor = UIColor(red: 37/255.0, green: 37/255.0, blue: 37.0/255.0, alpha: 1.0) 19 | UINavigationBar.appearance().standardAppearance = appearance 20 | UINavigationBar.appearance().scrollEdgeAppearance = appearance 21 | } else { 22 | UINavigationBar.appearance().barTintColor = .black 23 | UINavigationBar.appearance().tintColor = .white 24 | UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white] 25 | } 26 | } 27 | } 28 | 29 | extension UINavigationController { 30 | @objc override open var preferredStatusBarStyle: UIStatusBarStyle { 31 | return .lightContent 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /App/Application/AppConfigurations.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppConfiguration.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 25.02.19. 6 | // 7 | 8 | import Foundation 9 | 10 | final class AppConfiguration { 11 | lazy var apiKey: String = { 12 | guard let apiKey = Bundle.main.object(forInfoDictionaryKey: "ApiKey") as? String else { 13 | fatalError("ApiKey must not be empty in plist") 14 | } 15 | return apiKey 16 | }() 17 | lazy var apiBaseURL: String = { 18 | guard let apiBaseURL = Bundle.main.object(forInfoDictionaryKey: "ApiBaseURL") as? String else { 19 | fatalError("ApiBaseURL must not be empty in plist") 20 | } 21 | return apiBaseURL 22 | }() 23 | lazy var imagesBaseURL: String = { 24 | guard let imageBaseURL = Bundle.main.object(forInfoDictionaryKey: "ImageBaseURL") as? String else { 25 | fatalError("ApiBaseURL must not be empty in plist") 26 | } 27 | return imageBaseURL 28 | }() 29 | } 30 | -------------------------------------------------------------------------------- /App/Application/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 01.10.18. 6 | // 7 | 8 | import UIKit 9 | import MoviesSearch 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | let appDIContainer = AppDIContainer() 15 | var appFlowCoordinator: AppFlowCoordinator? 16 | var window: UIWindow? 17 | 18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 19 | 20 | AppAppearance.setupAppearance() 21 | 22 | window = UIWindow(frame: UIScreen.main.bounds) 23 | let navigationController = UINavigationController() 24 | 25 | window?.rootViewController = navigationController 26 | appFlowCoordinator = AppFlowCoordinator(navigationController: navigationController, 27 | appDIContainer: appDIContainer) 28 | appFlowCoordinator?.start() 29 | window?.makeKeyAndVisible() 30 | 31 | return true 32 | } 33 | 34 | func applicationDidEnterBackground(_ application: UIApplication) { 35 | CoreDataStorage.shared.saveContext() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /App/Application/AppFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppFlowCoordinator.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 03.03.19. 6 | // 7 | 8 | import UIKit 9 | 10 | final class AppFlowCoordinator { 11 | 12 | private weak var navigationController: UINavigationController? 13 | private let appDIContainer: AppDIContainer 14 | 15 | init(navigationController: UINavigationController, 16 | appDIContainer: AppDIContainer) { 17 | self.navigationController = navigationController 18 | self.appDIContainer = appDIContainer 19 | } 20 | 21 | func start() { 22 | guard let navigationController = navigationController else { return } 23 | 24 | // In App Flow we can check if user needs to login, if yes we would run login flow 25 | let moviesSearchModule = appDIContainer.makeMoviesSearchModule() 26 | moviesSearchModule.startMoviesSearchFlow(in: navigationController) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /App/Resources/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /App/Resources/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | App 4 | 5 | Created by Oleh Kudinov on 01.12.19. 6 | 7 | */ 8 | 9 | "Movies" = "Movies"; 10 | "Search results" = "Search results"; 11 | "Release Date" = "Release Date"; 12 | "To be announced" = "To be announced"; 13 | "Error" = "Error"; 14 | "No internet connection" = "No internet connection"; 15 | "Failed loading movies" = "Failed loading movies"; 16 | "Search Movies" = "Search Movies"; 17 | -------------------------------------------------------------------------------- /App/Resources/es.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /App/Resources/es.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | App 4 | 5 | Created by Oleh Kudinov on 01.12.19. 6 | 7 | */ 8 | 9 | "Movies" = "Películas"; 10 | "Search results" = "Resultados de búsqueda"; 11 | "Release Date" = "Fecha de lanzamiento"; 12 | "To be announced" = "Para ser anunciado"; 13 | "Error" = "Error"; 14 | "No internet connection" = "Sin conexión a internet"; 15 | "Failed loading movies" = "Error al descargar películas"; 16 | "Search Movies" = "Buscar películas"; 17 | -------------------------------------------------------------------------------- /AppUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /AppUITests/Presentation/MoviesScene/MoviesSceneUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesSceneUITests.swift 3 | // MoviesSceneUITests 4 | // 5 | // Created by Oleh Kudinov on 05.08.19. 6 | // 7 | 8 | import XCTest 9 | import MoviesSearch 10 | 11 | class MoviesSceneUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | 15 | continueAfterFailure = false 16 | XCUIApplication().launch() 17 | } 18 | 19 | // NOTE: for UI tests to work the keyboard of simulator must be on. 20 | // Keyboard shortcut COMMAND + SHIFT + K while simulator has focus 21 | func testOpenMovieDetails_whenSearchBatmanAndTapOnFirstResultRow_thenMovieDetailsViewOpensWithTitleBatman() { 22 | 23 | let app = XCUIApplication() 24 | 25 | // Search for Batman 26 | let searchText = "Batman Begins" 27 | app.searchFields[AccessibilityIdentifier.searchField].tap() 28 | if !app.keys["A"].waitForExistence(timeout: 5) { 29 | XCTFail("The keyboard could not be found. Use keyboard shortcut COMMAND + SHIFT + K while simulator has focus on text input") 30 | } 31 | 32 | _ = app.searchFields[AccessibilityIdentifier.searchField].waitForExistence(timeout: 10) 33 | app.searchFields[AccessibilityIdentifier.searchField].typeText(searchText) 34 | app.buttons["search"].tap() 35 | 36 | // Tap on first result row 37 | app.tables.cells.staticTexts[searchText].tap() 38 | 39 | // Make sure movie details view 40 | XCTAssertTrue(app.otherElements[AccessibilityIdentifier.movieDetailsView].waitForExistence(timeout: 5)) 41 | XCTAssertTrue(app.navigationBars[searchText].waitForExistence(timeout: 5)) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /DevPods/Authentication/Authentication.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'Authentication' 3 | s.version = '0.1.0' 4 | s.summary = 'A short description of Authentication.' 5 | 6 | s.description = <<-DESC 7 | TODO: Add long description of the pod here. 8 | DESC 9 | 10 | s.homepage = 'https://github.com/olehkudinovolx/Authentication' 11 | s.license = { :type => 'MIT', :file => 'LICENSE' } 12 | s.author = { 'olehkudinovolx' => 'oleh.kudinov@olx.com' } 13 | s.source = { :git => 'https://github.com/olehkudinovolx/Authentication.git', :tag => s.version.to_s } 14 | 15 | s.ios.deployment_target = '12.4' 16 | 17 | s.source_files = 'Authentication/Module/**/*.{swift}' 18 | 19 | s.resources = 'Authentication/Module/**/*.{xcassets,json,storyboard,xib,xcdatamodeld}' 20 | 21 | # 3rd party frameworks 22 | s.dependency 'Alamofire', '4.9.1' 23 | 24 | end 25 | -------------------------------------------------------------------------------- /DevPods/Authentication/Example/Authentication/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /DevPods/Authentication/Example/Authentication/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /DevPods/Authentication/Example/Authentication/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /DevPods/Authentication/Example/Authentication/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Authentication 4 | // 5 | // Created by olehkudinovolx on 12/07/2019. 6 | // Copyright (c) 2019 olehkudinovolx. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /DevPods/Authentication/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 olehkudinovolx 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /DevPods/Authentication/README.md: -------------------------------------------------------------------------------- 1 | # Authentication 2 | 3 | [![CI Status](https://img.shields.io/travis/olehkudinovolx/Authentication.svg?style=flat)](https://travis-ci.org/olehkudinovolx/Authentication) 4 | [![Version](https://img.shields.io/cocoapods/v/Authentication.svg?style=flat)](https://cocoapods.org/pods/Authentication) 5 | [![License](https://img.shields.io/cocoapods/l/Authentication.svg?style=flat)](https://cocoapods.org/pods/Authentication) 6 | [![Platform](https://img.shields.io/cocoapods/p/Authentication.svg?style=flat)](https://cocoapods.org/pods/Authentication) 7 | 8 | ## Example 9 | 10 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 11 | 12 | ## Requirements 13 | 14 | ## Installation 15 | 16 | Authentication is available through [CocoaPods](https://cocoapods.org). To install 17 | it, simply add the following line to your Podfile: 18 | 19 | ```ruby 20 | pod 'Authentication' 21 | ``` 22 | 23 | ## Author 24 | 25 | olehkudinovolx, oleh.kudinov@olx.com 26 | 27 | ## License 28 | 29 | Authentication is available under the MIT license. See the LICENSE file for more info. 30 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/Example/MoviesSearch/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/Example/MoviesSearch/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/Example/MoviesSearch/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/Example/MoviesSearch/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // MoviesSearch 4 | // 5 | // Created by olehkudinovolx on 11/30/2019. 6 | // Copyright (c) 2019 olehkudinovolx. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 olehkudinovolx 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'MoviesSearch' 3 | s.version = '0.1.0' 4 | s.summary = 'A short description of MoviesSearch.' 5 | 6 | s.description = <<-DESC 7 | TODO: Add long description of the pod here. 8 | DESC 9 | 10 | s.homepage = 'https://github.com/olehkudinovolx/MoviesSearch' 11 | s.license = { :type => 'MIT', :file => 'LICENSE' } 12 | s.author = { 'olehkudinovolx' => 'oleh.kudinov@olx.com' } 13 | s.source = { :git => 'https://github.com/olehkudinovolx/MoviesSearch.git', :tag => s.version.to_s } 14 | 15 | s.ios.deployment_target = '12.4' 16 | 17 | s.source_files = 'MoviesSearch/Module/**/*.{swift}' 18 | 19 | s.resources = 'MoviesSearch/Module/**/*.{xcassets,json,storyboard,xib,xcdatamodeld}' 20 | 21 | # Uncomment if static framework, and comment s.resources 22 | # s.resource_bundles = { 23 | # 'MoviesSearch' => ['MoviesSearch/Module/**/*.{xcassets,json,storyboard,xib,xcdatamodeld}'] 24 | # } 25 | 26 | s.test_spec 'Tests' do |test_spec| 27 | test_spec.source_files = 'MoviesSearch/Tests/**/*.{swift}' 28 | 29 | test_spec.dependency 'Quick' 30 | test_spec.dependency 'Nimble' 31 | test_spec.dependency 'iOSSnapshotTestCase' 32 | end 33 | 34 | s.dependency 'Networking' 35 | 36 | # Support versions before iOS 13 37 | s.weak_framework = 'SwiftUI' 38 | 39 | end 40 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Assets/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Common/Bundle+Resource.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Bundle+Resource.swift 3 | // MoviesSearch-framework 4 | // 5 | // Created by Oleh Kudinov on 10.12.19. 6 | // 7 | 8 | import Foundation 9 | 10 | extension Bundle { 11 | var resource: Bundle { 12 | // static framework 13 | if let resourceURL = resourceURL, 14 | let resourceBundle = Bundle(url: resourceURL.appendingPathComponent(ModuleName.name + ".bundle")) { 15 | return resourceBundle 16 | } else { 17 | // dynamic framework 18 | return self 19 | } 20 | } 21 | } 22 | 23 | private struct ModuleName { 24 | static var name: String = { 25 | String(reflecting: ModuleName.self).components(separatedBy: ".").first ?? "" 26 | }() 27 | } 28 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Common/Cancelable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Cancellable.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 10.03.19. 6 | // 7 | 8 | import Foundation 9 | 10 | public protocol Cancellable { 11 | func cancel() 12 | } 13 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Common/ConnectionError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ConnectionError.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 01.10.19. 6 | // 7 | 8 | import Foundation 9 | 10 | public protocol ConnectionError: Error { 11 | var isInternetConnectionError: Bool { get } 12 | } 13 | 14 | public extension Error { 15 | var isInternetConnectionError: Bool { 16 | guard let error = self as? ConnectionError, error.isInternetConnectionError else { 17 | return false 18 | } 19 | return true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Data/Network/APIEndpoints.swift: -------------------------------------------------------------------------------- 1 | // 2 | // APIEndpoints.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 01.10.18. 6 | // 7 | 8 | import Foundation 9 | import Networking 10 | 11 | struct APIEndpoints { 12 | 13 | static func getMovies(with moviesRequestDTO: MoviesRequestDTO) -> Endpoint { 14 | 15 | return Endpoint(path: "3/search/movie", 16 | method: .get, 17 | queryParametersEncodable: moviesRequestDTO) 18 | } 19 | 20 | static func getMoviePoster(path: String, width: Int) -> Endpoint { 21 | 22 | let sizes = [92, 154, 185, 342, 500, 780] 23 | let closestWidth = sizes.enumerated().min { abs($0.1 - width) < abs($1.1 - width) }?.element ?? sizes.first! 24 | 25 | return Endpoint(path: "t/p/w\(closestWidth)\(path)", 26 | method: .get, 27 | responseDecoder: RawDataResponseDecoder()) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Data/Network/DataMapping/MoviesRequestDTO+Mapping.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesRequestDTO+Mapping.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 22/03/2020. 6 | // 7 | 8 | import Foundation 9 | 10 | struct MoviesRequestDTO: Encodable { 11 | let query: String 12 | let page: Int 13 | } 14 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Data/PersistentStorages/CoreDataStorage/CoreDataStorage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataStorage.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 26/03/2020. 6 | // 7 | 8 | import CoreData 9 | 10 | enum CoreDataStorageError: Error { 11 | case readError(Error) 12 | case saveError(Error) 13 | case deleteError(Error) 14 | } 15 | 16 | public final class CoreDataStorage { 17 | 18 | public static let shared = CoreDataStorage() 19 | 20 | // MARK: - Core Data stack 21 | private lazy var persistentContainer: NSPersistentContainer = { 22 | guard let modelURL = Bundle(for: Self.self).resource.url(forResource: "CoreDataStorage", withExtension: "momd"), 23 | let mom = NSManagedObjectModel(contentsOf: modelURL) 24 | else { 25 | fatalError("Unable to located Core Data model") 26 | } 27 | let container = NSPersistentContainer(name: "Name", managedObjectModel: mom) 28 | container.loadPersistentStores { _, error in 29 | if let error = error as NSError? { 30 | // Log to Crashlytics 31 | debugPrint("CoreDataStorage Unresolved error \(error), \(error.userInfo)") 32 | } 33 | } 34 | return container 35 | }() 36 | 37 | // MARK: - Core Data Saving support 38 | public func saveContext () { 39 | let context = persistentContainer.viewContext 40 | if context.hasChanges { 41 | do { 42 | try context.save() 43 | } catch { 44 | // Log to Crashlytics 45 | debugPrint("CoreDataStorage Unresolved error \(error), \((error as NSError).userInfo)") 46 | } 47 | } 48 | } 49 | 50 | func performBackgroundTask(_ block: @escaping (NSManagedObjectContext) -> Void) { 51 | persistentContainer.performBackgroundTask(block) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Data/PersistentStorages/CoreDataStorage/CoreDataStorage.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | CoreDataStorage 2.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Data/PersistentStorages/CoreDataStorage/CoreDataStorage.xcdatamodeld/CoreDataStorage.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Data/PersistentStorages/MoviesQueriesStorage/CoreDataStorage/EntityMapping/MovieQueryEntity+Mapping.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovieQueryEntity+Mapping.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 16.08.19. 6 | // 7 | 8 | import Foundation 9 | import CoreData 10 | 11 | extension MovieQueryEntity { 12 | convenience init(movieQuery: MovieQuery, insertInto context: NSManagedObjectContext) { 13 | self.init(context: context) 14 | query = movieQuery.query 15 | createdAt = Date() 16 | } 17 | } 18 | 19 | extension MovieQueryEntity { 20 | func toDomain() -> MovieQuery { 21 | return .init(query: query ?? "") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Data/PersistentStorages/MoviesQueriesStorage/MoviesQueriesStorage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesQueriesStorage.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 16.08.19. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol MoviesQueriesStorage { 11 | func fetchRecentsQueries(maxCount: Int, completion: @escaping (Result<[MovieQuery], Error>) -> Void) 12 | func saveRecentQuery(query: MovieQuery, completion: @escaping (Result) -> Void) 13 | } 14 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Data/PersistentStorages/MoviesQueriesStorage/UserDefaultsStorage/DataMapping/MovieQueryUDS+Mapping.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovieQueryUDS+Mapping.swift 3 | // Data 4 | // 5 | // Created by Oleh Kudinov on 12.08.19. 6 | // Copyright © 2019 Oleh Kudinov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct MovieQueriesListUDS: Codable { 12 | var list: [MovieQueryUDS] 13 | } 14 | 15 | struct MovieQueryUDS: Codable { 16 | let query: String 17 | } 18 | 19 | extension MovieQueryUDS { 20 | init(movieQuery: MovieQuery) { 21 | query = movieQuery.query 22 | } 23 | } 24 | 25 | extension MovieQueryUDS { 26 | func toDomain() -> MovieQuery { 27 | return .init(query: query) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Data/PersistentStorages/MoviesResponseStorage/MoviesResponseStorage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesResponseStorage.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 05/04/2020. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol MoviesResponseStorage { 11 | func getResponse(for request: MoviesRequestDTO, completion: @escaping (Result) -> Void) 12 | func save(response: MoviesResponseDTO, for requestDto: MoviesRequestDTO) 13 | } 14 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Data/Repositories/DefaultMoviesQueriesRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultMoviesQueriesRepository.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 15.02.19. 6 | // 7 | 8 | import Foundation 9 | import Networking 10 | 11 | final class DefaultMoviesQueriesRepository { 12 | 13 | private let dataTransferService: DataTransferService 14 | private var moviesQueriesPersistentStorage: MoviesQueriesStorage 15 | 16 | init(dataTransferService: DataTransferService, 17 | moviesQueriesPersistentStorage: MoviesQueriesStorage) { 18 | self.dataTransferService = dataTransferService 19 | self.moviesQueriesPersistentStorage = moviesQueriesPersistentStorage 20 | } 21 | } 22 | 23 | extension DefaultMoviesQueriesRepository: MoviesQueriesRepository { 24 | 25 | func fetchRecentsQueries(maxCount: Int, completion: @escaping (Result<[MovieQuery], Error>) -> Void) { 26 | return moviesQueriesPersistentStorage.fetchRecentsQueries(maxCount: maxCount, completion: completion) 27 | } 28 | 29 | func saveRecentQuery(query: MovieQuery, completion: @escaping (Result) -> Void) { 30 | moviesQueriesPersistentStorage.saveRecentQuery(query: query, completion: completion) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Data/Repositories/DefaultPosterImagesRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultPosterImagesRepository.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 01.10.18. 6 | // 7 | 8 | import Foundation 9 | import Networking 10 | 11 | final class DefaultPosterImagesRepository { 12 | 13 | private let dataTransferService: DataTransferService 14 | 15 | init(dataTransferService: DataTransferService) { 16 | self.dataTransferService = dataTransferService 17 | } 18 | } 19 | 20 | extension DefaultPosterImagesRepository: PosterImagesRepository { 21 | 22 | func fetchImage(with imagePath: String, width: Int, completion: @escaping (Result) -> Void) -> Cancellable? { 23 | 24 | let endpoint = APIEndpoints.getMoviePoster(path: imagePath, width: width) 25 | let task = RepositoryTask() 26 | task.networkTask = dataTransferService.request(with: endpoint) { (result: Result) in 27 | 28 | let result = result.mapError { $0 as Error } 29 | DispatchQueue.main.async { completion(result) } 30 | } 31 | return task 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Data/Repositories/Utils/RepositoryTask.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RepositoryTask.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 25.10.19. 6 | // 7 | 8 | import Foundation 9 | import Networking 10 | 11 | class RepositoryTask: Cancellable { 12 | var networkTask: NetworkCancellable? 13 | var isCancelled: Bool = false 14 | 15 | func cancel() { 16 | networkTask?.cancel() 17 | isCancelled = true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Domain/Entities/Movie.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Movie.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 01.10.18. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Movie: Equatable, Identifiable { 11 | typealias Identifier = String 12 | enum Genre { 13 | case adventure 14 | case scienceFiction 15 | } 16 | let id: Identifier 17 | let title: String? 18 | let genre: Genre? 19 | let posterPath: String? 20 | let overview: String? 21 | let releaseDate: Date? 22 | } 23 | 24 | struct MoviesPage: Equatable { 25 | let page: Int 26 | let totalPages: Int 27 | let movies: [Movie] 28 | } 29 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Domain/Entities/MovieQuery.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovieQuery.swift 3 | // App 4 | // 5 | // Created by Oleh on 03.10.18. 6 | // 7 | 8 | import Foundation 9 | 10 | struct MovieQuery: Equatable { 11 | let query: String 12 | } 13 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Domain/Interfaces/Repositories/MoviesQueriesRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesQueriesRepositoryInterface.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 15.02.19. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol MoviesQueriesRepository { 11 | func fetchRecentsQueries(maxCount: Int, completion: @escaping (Result<[MovieQuery], Error>) -> Void) 12 | func saveRecentQuery(query: MovieQuery, completion: @escaping (Result) -> Void) 13 | } 14 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Domain/Interfaces/Repositories/MoviesRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesRepositoryInterfaces.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 01.10.18. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol MoviesRepository { 11 | @discardableResult 12 | func fetchMoviesList(query: MovieQuery, page: Int, 13 | cached: @escaping (MoviesPage) -> Void, 14 | completion: @escaping (Result) -> Void) -> Cancellable? 15 | } 16 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Domain/Interfaces/Repositories/PosterImagesRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PosterImagesRepositoryInterface.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 01.10.18. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol PosterImagesRepository { 11 | func fetchImage(with imagePath: String, width: Int, completion: @escaping (Result) -> Void) -> Cancellable? 12 | } 13 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Domain/UseCases/FetchRecentMovieQueriesUseCase.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FetchRecentMovieQueriesUseCase.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 11.08.19. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol FetchRecentMovieQueriesUseCase { 11 | func execute(requestValue: FetchRecentMovieQueriesUseCaseRequestValue, 12 | completion: @escaping (Result<[MovieQuery], Error>) -> Void) -> Cancellable? 13 | } 14 | 15 | final class DefaultFetchRecentMovieQueriesUseCase: FetchRecentMovieQueriesUseCase { 16 | 17 | private let moviesQueriesRepository: MoviesQueriesRepository 18 | 19 | init(moviesQueriesRepository: MoviesQueriesRepository) { 20 | self.moviesQueriesRepository = moviesQueriesRepository 21 | } 22 | 23 | func execute(requestValue: FetchRecentMovieQueriesUseCaseRequestValue, 24 | completion: @escaping (Result<[MovieQuery], Error>) -> Void) -> Cancellable? { 25 | 26 | moviesQueriesRepository.fetchRecentsQueries(maxCount: requestValue.maxCount, completion: completion) 27 | return nil 28 | } 29 | } 30 | 31 | struct FetchRecentMovieQueriesUseCaseRequestValue { 32 | let maxCount: Int 33 | } 34 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Domain/UseCases/SearchMoviesUseCase.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchMoviesUseCase.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 22.02.19. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol SearchMoviesUseCase { 11 | func execute(requestValue: SearchMoviesUseCaseRequestValue, 12 | cached: @escaping (MoviesPage) -> Void, 13 | completion: @escaping (Result) -> Void) -> Cancellable? 14 | } 15 | 16 | final class DefaultSearchMoviesUseCase: SearchMoviesUseCase { 17 | 18 | private let moviesRepository: MoviesRepository 19 | private let moviesQueriesRepository: MoviesQueriesRepository 20 | 21 | init(moviesRepository: MoviesRepository, 22 | moviesQueriesRepository: MoviesQueriesRepository) { 23 | 24 | self.moviesRepository = moviesRepository 25 | self.moviesQueriesRepository = moviesQueriesRepository 26 | } 27 | 28 | func execute(requestValue: SearchMoviesUseCaseRequestValue, 29 | cached: @escaping (MoviesPage) -> Void, 30 | completion: @escaping (Result) -> Void) -> Cancellable? { 31 | 32 | return moviesRepository.fetchMoviesList(query: requestValue.query, 33 | page: requestValue.page, 34 | cached: cached, 35 | completion: { result in 36 | 37 | if case .success = result { 38 | self.moviesQueriesRepository.saveRecentQuery(query: requestValue.query) { _ in } 39 | } 40 | 41 | completion(result) 42 | }) 43 | } 44 | } 45 | 46 | struct SearchMoviesUseCaseRequestValue { 47 | let query: MovieQuery 48 | let page: Int 49 | } 50 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Module.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesSearchModule.swift 3 | // MoviesSearch 4 | // 5 | // Created by Oleh Kudinov on 23.12.19. 6 | // 7 | 8 | import UIKit 9 | import Networking 10 | 11 | public struct ModuleDependencies { 12 | let apiDataTransferService: DataTransferService 13 | let imageDataTransferService: DataTransferService 14 | 15 | public init (apiDataTransferService: DataTransferService, imageDataTransferService: DataTransferService) { 16 | self.apiDataTransferService = apiDataTransferService 17 | self.imageDataTransferService = imageDataTransferService 18 | } 19 | } 20 | 21 | public struct Module { 22 | 23 | private let diContainer: DIContainer 24 | 25 | public init(dependencies: ModuleDependencies) { 26 | self.diContainer = DIContainer(dependencies: dependencies) 27 | } 28 | 29 | public func startMoviesSearchFlow(in navigationController: UINavigationController) { 30 | let flow = diContainer.makeMoviesSearchFlowCoordinator(navigationController: navigationController) 31 | flow.start() 32 | } 33 | } 34 | 35 | // Note: We can create ChatPresenter Interface and add it to ModuleDependencies if we want to delegate 36 | // Chat feature to App and avoid dependency on Chat module from this module(same can be done by using closure) 37 | public protocol ChatPresenter { 38 | func openChatForUser(inView: UIViewController) 39 | } 40 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/MoviesScene/Behaviors/BackButtonEmptyTitleNavigationBarBehavior.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BackButtonEmptyTitleNavigationBarBehavior.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 03/04/2020. 6 | // 7 | 8 | import UIKit 9 | 10 | struct BackButtonEmptyTitleNavigationBarBehavior: ViewControllerLifecycleBehavior { 11 | 12 | func viewDidLoad(viewController: UIViewController) { 13 | 14 | viewController.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/MoviesScene/Behaviors/BlackStyleNavigationBarBehavior.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BlackStyleNavigationBarBehavior.swift 3 | // Alamofire 4 | // 5 | // Created by Oleh Kudinov on 26/05/2020. 6 | // 7 | 8 | import UIKit 9 | 10 | struct BlackStyleNavigationBarBehavior: ViewControllerLifecycleBehavior { 11 | 12 | func viewDidLoad(viewController: UIViewController) { 13 | 14 | viewController.navigationController?.navigationBar.barStyle = .black 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/MoviesScene/MovieDetails/View/MovieDetailsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovieDetailsViewController.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 04.08.19. 6 | // Copyright (c) 2019 All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | final class MovieDetailsViewController: UIViewController, StoryboardInstantiable { 12 | 13 | @IBOutlet private var posterImageView: UIImageView! 14 | @IBOutlet private var overviewTextView: UITextView! 15 | 16 | private var viewModel: MovieDetailsViewModel! 17 | 18 | // MARK: - Lifecycle 19 | 20 | static func create(with viewModel: MovieDetailsViewModel) -> MovieDetailsViewController { 21 | let view = MovieDetailsViewController.instantiateViewController(Bundle(for: Self.self).resource) 22 | view.viewModel = viewModel 23 | return view 24 | } 25 | 26 | override func viewDidLoad() { 27 | super.viewDidLoad() 28 | setupViews() 29 | bind(to: viewModel) 30 | } 31 | 32 | private func bind(to viewModel: MovieDetailsViewModel) { 33 | viewModel.posterImage.observe(on: self) { [weak self] in self?.posterImageView.image = $0.flatMap(UIImage.init) } 34 | } 35 | 36 | override func viewDidLayoutSubviews() { 37 | super.viewDidLayoutSubviews() 38 | viewModel.updatePosterImage(width: Int(posterImageView.imageSizeAfterAspectFit.scaledSize.width)) 39 | } 40 | 41 | // MARK: - Private 42 | 43 | private func setupViews() { 44 | title = viewModel.title 45 | overviewTextView.text = viewModel.overview 46 | posterImageView.isHidden = viewModel.isPosterImageHidden 47 | view.accessibilityIdentifier = AccessibilityIdentifier.movieDetailsView 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/MoviesScene/MoviesList/View/MoviesListTableView/Cells/MoviesListItemCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesListItemCell.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 01.10.18. 6 | // 7 | 8 | import UIKit 9 | 10 | final class MoviesListItemCell: UITableViewCell { 11 | 12 | static let reuseIdentifier = String(describing: MoviesListItemCell.self) 13 | static let height = CGFloat(130) 14 | 15 | @IBOutlet private var titleLabel: UILabel! 16 | @IBOutlet private var dateLabel: UILabel! 17 | @IBOutlet private var overviewLabel: UILabel! 18 | @IBOutlet private var posterImageView: UIImageView! 19 | 20 | private var viewModel: MoviesListItemViewModel! 21 | private var posterImagesRepository: PosterImagesRepository? 22 | private var imageLoadTask: Cancellable? { willSet { imageLoadTask?.cancel() } } 23 | 24 | func fill(with viewModel: MoviesListItemViewModel, posterImagesRepository: PosterImagesRepository?) { 25 | self.viewModel = viewModel 26 | self.posterImagesRepository = posterImagesRepository 27 | 28 | titleLabel.text = viewModel.title 29 | dateLabel.text = viewModel.releaseDate 30 | overviewLabel.text = viewModel.overview 31 | updatePosterImage(width: Int(posterImageView.imageSizeAfterAspectFit.scaledSize.width)) 32 | } 33 | 34 | private func updatePosterImage(width: Int) { 35 | posterImageView.image = nil 36 | guard let posterImagePath = viewModel.posterImagePath else { return } 37 | 38 | imageLoadTask = posterImagesRepository?.fetchImage(with: posterImagePath, width: width) { [weak self] result in 39 | guard let self = self else { return } 40 | guard self.viewModel.posterImagePath == posterImagePath else { return } 41 | if case let .success(data) = result { 42 | self.posterImageView.image = UIImage(data: data) 43 | } 44 | self.imageLoadTask = nil 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/MoviesScene/MoviesList/ViewModel/MoviesListItemViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesListItemViewModel.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 18.02.19. 6 | // 7 | 8 | // **Note**: This item view model is to display data and does not contain any domain model to prevent views accessing it 9 | 10 | import Foundation 11 | 12 | struct MoviesListItemViewModel: Equatable { 13 | let title: String 14 | let overview: String 15 | let releaseDate: String 16 | let posterImagePath: String? 17 | } 18 | 19 | extension MoviesListItemViewModel { 20 | 21 | init(movie: Movie) { 22 | self.title = movie.title ?? "" 23 | self.posterImagePath = movie.posterPath 24 | self.overview = movie.overview ?? "" 25 | if let releaseDate = movie.releaseDate { 26 | self.releaseDate = "\(NSLocalizedString("Release Date", comment: "")): \(dateFormatter.string(from: releaseDate))" 27 | } else { 28 | self.releaseDate = NSLocalizedString("To be announced", comment: "") 29 | } 30 | } 31 | } 32 | 33 | private let dateFormatter: DateFormatter = { 34 | let formatter = DateFormatter() 35 | formatter.dateStyle = .medium 36 | return formatter 37 | }() 38 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/MoviesScene/MoviesQueriesList/View/SwiftUI/MoviesQueryListView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesQueryListView.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 16.08.19. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | 11 | @available(iOS 13.0, *) 12 | extension MoviesQueryListItemViewModel: Identifiable { } 13 | 14 | @available(iOS 13.0, *) 15 | struct MoviesQueryListView: View { 16 | @ObservedObject var viewModelWrapper: MoviesQueryListViewModelWrapper 17 | 18 | var body: some View { 19 | List(viewModelWrapper.items) { item in 20 | Button(action: { 21 | self.viewModelWrapper.viewModel?.didSelect(item: item) 22 | }) { 23 | Text(item.query) 24 | } 25 | } 26 | .onAppear { 27 | self.viewModelWrapper.viewModel?.viewWillAppear() 28 | } 29 | } 30 | } 31 | 32 | @available(iOS 13.0, *) 33 | final class MoviesQueryListViewModelWrapper: ObservableObject { 34 | var viewModel: MoviesQueryListViewModel? 35 | @Published var items: [MoviesQueryListItemViewModel] = [] 36 | 37 | init(viewModel: MoviesQueryListViewModel?) { 38 | self.viewModel = viewModel 39 | viewModel?.items.observe(on: self) { [weak self] values in self?.items = values } 40 | } 41 | } 42 | 43 | #if DEBUG 44 | @available(iOS 13.0, *) 45 | struct MoviesQueryListView_Previews: PreviewProvider { 46 | static var previews: some View { 47 | MoviesQueryListView(viewModelWrapper: previewViewModelWrapper) 48 | } 49 | 50 | static var previewViewModelWrapper: MoviesQueryListViewModelWrapper = { 51 | var viewModel = MoviesQueryListViewModelWrapper(viewModel: nil) 52 | viewModel.items = [MoviesQueryListItemViewModel(query: "item 1"), 53 | MoviesQueryListItemViewModel(query: "item 2") 54 | ] 55 | return viewModel 56 | }() 57 | } 58 | #endif 59 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/MoviesScene/MoviesQueriesList/View/UIKit/Cells/MoviesQueriesItemCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesQueriesItemCell.swift 3 | // App 4 | // 5 | // Created by Oleh on 03.10.18. 6 | // 7 | 8 | import UIKit 9 | 10 | final class MoviesQueriesItemCell: UITableViewCell { 11 | static let height = CGFloat(50) 12 | static let reuseIdentifier = String(describing: MoviesQueriesItemCell.self) 13 | 14 | @IBOutlet private var titleLabel: UILabel! 15 | 16 | func fill(with suggestion: MoviesQueryListItemViewModel) { 17 | self.titleLabel.text = suggestion.query 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/MoviesScene/MoviesQueriesList/ViewModel/MoviesQueryListItemViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesQueryListItemViewModel.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 25.08.19. 6 | // 7 | 8 | import Foundation 9 | 10 | class MoviesQueryListItemViewModel { 11 | let query: String 12 | 13 | init(query: String) { 14 | self.query = query 15 | } 16 | } 17 | 18 | extension MoviesQueryListItemViewModel: Equatable { 19 | static func == (lhs: MoviesQueryListItemViewModel, rhs: MoviesQueryListItemViewModel) -> Bool { 20 | return lhs.query == rhs.query 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/Utils/AccessibilityIdentifier.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AccessibilityIdentifier.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 08.01.20. 6 | // 7 | 8 | import Foundation 9 | 10 | public struct AccessibilityIdentifier { 11 | public static let movieDetailsView = "AccessibilityIdentifierMovieDetailsView" 12 | public static let searchField = "AccessibilityIdentifierSearchMovies" 13 | } 14 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/Utils/Extensions/CGSize+ScaledSize.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CGSize+ScaledSize.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 21/03/2020. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | extension CGSize { 12 | var scaledSize: CGSize { 13 | .init(width: width * UIScreen.main.scale, height: height * UIScreen.main.scale) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/Utils/Extensions/DataTransferError+ConnectionError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataTransferError+ConnectionError.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 29.10.19. 6 | // 7 | 8 | import Foundation 9 | import Networking 10 | 11 | extension DataTransferError: ConnectionError { 12 | public var isInternetConnectionError: Bool { 13 | guard case let DataTransferError.networkFailure(networkError) = self, 14 | case .notConnected = networkError else { 15 | return false 16 | } 17 | return true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/Utils/Extensions/UIImageView+ImageSizeAfterAspectFit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+ImageSizeAfterAspectFit.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 21/03/2020. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | extension UIImageView { 12 | 13 | var imageSizeAfterAspectFit: CGSize { 14 | var newWidth: CGFloat 15 | var newHeight: CGFloat 16 | 17 | guard let image = image else { return frame.size } 18 | 19 | if image.size.height >= image.size.width { 20 | newHeight = frame.size.height 21 | newWidth = ((image.size.width / (image.size.height)) * newHeight) 22 | 23 | if CGFloat(newWidth) > (frame.size.width) { 24 | let diff = (frame.size.width) - newWidth 25 | newHeight = newHeight + CGFloat(diff) / newHeight * newHeight 26 | newWidth = frame.size.width 27 | } 28 | } else { 29 | newWidth = frame.size.width 30 | newHeight = (image.size.height / image.size.width) * newWidth 31 | 32 | if newHeight > frame.size.height { 33 | let diff = Float((frame.size.height) - newHeight) 34 | newWidth = newWidth + CGFloat(diff) / newWidth * newWidth 35 | newHeight = frame.size.height 36 | } 37 | } 38 | return .init(width: newWidth, height: newHeight) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/Utils/Extensions/UIViewController+ActivityIndicator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+make.swift 3 | // MoviesSearch 4 | // 5 | // Created by Oleh Kudinov on 29/09/2020. 6 | // 7 | 8 | import UIKit 9 | 10 | extension UITableViewController { 11 | 12 | func makeActivityIndicator(size: CGSize) -> UIActivityIndicatorView { 13 | let style: UIActivityIndicatorView.Style 14 | if #available(iOS 12.0, *) { 15 | if self.traitCollection.userInterfaceStyle == .dark { 16 | style = .white 17 | } else { 18 | style = .gray 19 | } 20 | } else { 21 | style = .gray 22 | } 23 | 24 | let activityIndicator = UIActivityIndicatorView(style: style) 25 | activityIndicator.startAnimating() 26 | activityIndicator.isHidden = false 27 | activityIndicator.frame = .init(origin: .zero, size: size) 28 | 29 | return activityIndicator 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/Utils/Extensions/UIViewController+AddChild.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+AddChild.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 25.08.19. 6 | // 7 | 8 | import UIKit 9 | 10 | extension UIViewController { 11 | 12 | func add(child: UIViewController, container: UIView) { 13 | addChild(child) 14 | child.view.frame = container.bounds 15 | container.addSubview(child.view) 16 | child.didMove(toParent: self) 17 | } 18 | 19 | func remove() { 20 | guard parent != nil else { 21 | return 22 | } 23 | willMove(toParent: nil) 24 | removeFromParent() 25 | view.removeFromSuperview() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/Utils/LiteralBundleImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Image+LiteralBundle.swift 3 | // MoviesSearch-framework 4 | // 5 | // Created by Oleh Kudinov on 10.12.19. 6 | // 7 | 8 | import Foundation 9 | 10 | final class LiteralBundleImage: _ExpressibleByImageLiteral { 11 | let image: UIImage? 12 | 13 | required init(imageLiteralResourceName name: String) { 14 | image = UIImage(named: name, in: Bundle(for: Self.self).resource, compatibleWith: nil) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/Utils/LoadingView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoadingView.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 28/03/2020. 6 | // 7 | 8 | import UIKit 9 | 10 | public class LoadingView { 11 | 12 | internal static var spinner: UIActivityIndicatorView? 13 | 14 | public static func show() { 15 | DispatchQueue.main.async { 16 | NotificationCenter.default.addObserver(self, selector: #selector(update), name: UIDevice.orientationDidChangeNotification, object: nil) 17 | if spinner == nil, let window = UIApplication.shared.keyWindow { 18 | let frame = UIScreen.main.bounds 19 | let spinner = UIActivityIndicatorView(frame: frame) 20 | spinner.backgroundColor = UIColor.black.withAlphaComponent(0.2) 21 | spinner.style = .whiteLarge 22 | window.addSubview(spinner) 23 | 24 | spinner.startAnimating() 25 | self.spinner = spinner 26 | } 27 | } 28 | } 29 | 30 | public static func hide() { 31 | DispatchQueue.main.async { 32 | guard let spinner = spinner else { return } 33 | spinner.stopAnimating() 34 | spinner.removeFromSuperview() 35 | self.spinner = nil 36 | } 37 | } 38 | 39 | @objc public static func update() { 40 | DispatchQueue.main.async { 41 | if spinner != nil { 42 | hide() 43 | show() 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/Utils/Observable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Observable.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 16.02.19. 6 | // 7 | 8 | import Foundation 9 | 10 | final public class Observable { 11 | 12 | private struct Observer { 13 | weak var observer: AnyObject? 14 | let block: (Value) -> Void 15 | } 16 | 17 | private var observers = [Observer]() 18 | 19 | public var value: Value { 20 | didSet { notifyObservers() } 21 | } 22 | 23 | public init(_ value: Value) { 24 | self.value = value 25 | } 26 | 27 | public func observe(on observer: AnyObject, observerBlock: @escaping (Value) -> Void) { 28 | observers.append(Observer(observer: observer, block: observerBlock)) 29 | observerBlock(self.value) 30 | } 31 | 32 | public func remove(observer: AnyObject) { 33 | observers = observers.filter { $0.observer !== observer } 34 | } 35 | 36 | private func notifyObservers() { 37 | for observer in observers { 38 | DispatchQueue.main.async { observer.block(self.value) } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/Utils/Protocols/Alertable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Alertable.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 01.10.18. 6 | // 7 | 8 | import UIKit 9 | 10 | public protocol Alertable {} 11 | public extension Alertable where Self: UIViewController { 12 | 13 | func showAlert(title: String = "", message: String, preferredStyle: UIAlertController.Style = .alert, completion: (() -> Void)? = nil) { 14 | let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) 15 | alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)) 16 | self.present(alert, animated: true, completion: completion) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Module/Presentation/Utils/Protocols/StoryboardInstantiable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StoryboardInstantiable.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 03.03.19. 6 | // 7 | 8 | import UIKit 9 | 10 | public protocol StoryboardInstantiable: NSObjectProtocol { 11 | associatedtype T 12 | static var defaultFileName: String { get } 13 | static func instantiateViewController(_ bundle: Bundle?) -> T 14 | } 15 | 16 | public extension StoryboardInstantiable where Self: UIViewController { 17 | static var defaultFileName: String { 18 | return NSStringFromClass(Self.self).components(separatedBy: ".").last! 19 | } 20 | 21 | static func instantiateViewController(_ bundle: Bundle? = nil) -> Self { 22 | let fileName = defaultFileName 23 | let storyboard = UIStoryboard(name: fileName, bundle: bundle) 24 | guard let vc = storyboard.instantiateInitialViewController() as? Self else { 25 | 26 | fatalError("Cannot instantiate initial view controller \(Self.self) from storyboard with name \(fileName)") 27 | } 28 | return vc 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Tests/Mocks/Movie+Stub.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Movie+Stub.swift 3 | // ExampleMVVM 4 | // 5 | // Created by Oleh Kudinov on 17/03/2020. 6 | // 7 | 8 | import Foundation 9 | @testable import MoviesSearch 10 | 11 | extension Movie { 12 | static func stub(id: Movie.Identifier = "id1", 13 | title: String = "title1" , 14 | genre: Movie.Genre = .adventure, 15 | posterPath: String? = "/1", 16 | overview: String = "overview1", 17 | releaseDate: Date? = nil) -> Self { 18 | Movie(id: id, 19 | title: title, 20 | genre: genre, 21 | posterPath: posterPath, 22 | overview: overview, 23 | releaseDate: releaseDate) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Tests/Presentation/MoviesScene/Mocks/PosterImagesRepositoryMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PosterImagesRepositoryMock.swift 3 | // AppTests 4 | // 5 | // Created by Oleh Kudinov on 17.08.19. 6 | // 7 | 8 | import Foundation 9 | import XCTest 10 | @testable import MoviesSearch 11 | 12 | class PosterImagesRepositoryMock: PosterImagesRepository { 13 | var expectation: XCTestExpectation? 14 | var error: Error? 15 | var image = Data() 16 | var validateInput: ((String, Int) -> Void)? 17 | 18 | func fetchImage(with imagePath: String, width: Int, completion: @escaping (Result) -> Void) -> Cancellable? { 19 | validateInput?(imagePath, width) 20 | if let error = error { 21 | completion(.failure(error)) 22 | } else { 23 | completion(.success(image)) 24 | } 25 | expectation?.fulfill() 26 | return nil 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/MoviesSearch/Tests/Presentation/MoviesScene/MovieDetailsViewModelTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovieDetailsViewModelTests.swift 3 | // AppTests 4 | // 5 | // Created by Oleh Kudinov on 17.08.19. 6 | // 7 | 8 | import XCTest 9 | @testable import MoviesSearch 10 | 11 | class MovieDetailsViewModelTests: XCTestCase { 12 | 13 | private enum PosterImageDowloadError: Error { 14 | case someError 15 | } 16 | 17 | func test_updatePosterImageWithWidthEventReceived_thenImageWithThisWidthIsDownloaded() { 18 | // given 19 | let posterImagesRepository = PosterImagesRepositoryMock() 20 | posterImagesRepository.expectation = self.expectation(description: "Image with download") 21 | let expectedImage = "image data".data(using: .utf8)! 22 | posterImagesRepository.image = expectedImage 23 | 24 | let viewModel = DefaultMovieDetailsViewModel(movie: Movie.stub(posterPath: "posterPath"), 25 | posterImagesRepository: posterImagesRepository) 26 | 27 | posterImagesRepository.validateInput = { (imagePath: String, width: Int) in 28 | XCTAssertEqual(imagePath, "posterPath") 29 | XCTAssertEqual(width, 200) 30 | } 31 | 32 | // when 33 | viewModel.updatePosterImage(width: 200) 34 | 35 | // then 36 | waitForExpectations(timeout: 5, handler: nil) 37 | XCTAssertEqual(viewModel.posterImage.value, expectedImage) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /DevPods/MoviesSearch/README.md: -------------------------------------------------------------------------------- 1 | # MoviesSearch 2 | 3 | [![CI Status](https://img.shields.io/travis/olehkudinovolx/MoviesSearch.svg?style=flat)](https://travis-ci.org/olehkudinovolx/MoviesSearch) 4 | [![Version](https://img.shields.io/cocoapods/v/MoviesSearch.svg?style=flat)](https://cocoapods.org/pods/MoviesSearch) 5 | [![License](https://img.shields.io/cocoapods/l/MoviesSearch.svg?style=flat)](https://cocoapods.org/pods/MoviesSearch) 6 | [![Platform](https://img.shields.io/cocoapods/p/MoviesSearch.svg?style=flat)](https://cocoapods.org/pods/MoviesSearch) 7 | 8 | ## Example 9 | 10 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 11 | 12 | ## Requirements 13 | 14 | ## Installation 15 | 16 | MoviesSearch is available through [CocoaPods](https://cocoapods.org). To install 17 | it, simply add the following line to your Podfile: 18 | 19 | ```ruby 20 | pod 'MoviesSearch' 21 | ``` 22 | 23 | ## Author 24 | 25 | olehkudinovolx, oleh.kudinov@olx.com 26 | 27 | ## License 28 | 29 | MoviesSearch is available under the MIT license. See the LICENSE file for more info. 30 | -------------------------------------------------------------------------------- /DevPods/Networking/Example/Networking/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /DevPods/Networking/Example/Networking/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /DevPods/Networking/Example/Networking/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /DevPods/Networking/Example/Networking/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Networking 4 | // 5 | // Created by olehkudinovolx on 11/30/2019. 6 | // Copyright (c) 2019 olehkudinovolx. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Networking 11 | 12 | class ViewController: UIViewController { 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | // Do any additional setup after loading the view, typically from a nib. 17 | } 18 | 19 | override func didReceiveMemoryWarning() { 20 | super.didReceiveMemoryWarning() 21 | // Dispose of any resources that can be recreated. 22 | } 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /DevPods/Networking/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 olehkudinovolx 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /DevPods/Networking/Networking.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'Networking' 3 | s.version = '0.1.0' 4 | s.summary = 'A short description of Networking.' 5 | 6 | s.description = <<-DESC 7 | TODO: Add long description of the pod here. 8 | DESC 9 | 10 | s.homepage = 'https://github.com/olehkudinovolx/Networking' 11 | s.license = { :type => 'MIT', :file => 'LICENSE' } 12 | s.author = { 'olehkudinovolx' => 'oleh.kudinov@olx.com' } 13 | s.source = { :git => 'https://github.com/olehkudinovolx/Networking.git', :tag => s.version.to_s } 14 | 15 | s.ios.deployment_target = '12.4' 16 | 17 | s.source_files = 'Networking/Module/**/*.{swift}' 18 | 19 | s.resources = 'Networking/Module/**/*.{xcassets,json,storyboard,xib,xcdatamodeld}' 20 | 21 | s.test_spec 'Tests' do |test_spec| 22 | test_spec.source_files = 'Networking/Tests/**/*.{swift}' 23 | end 24 | 25 | end 26 | -------------------------------------------------------------------------------- /DevPods/Networking/Networking/Module/NetworkConfig.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ServiceConfig.swift 3 | // App 4 | // 5 | // Created by Oleh Kudinov on 01.10.18. 6 | // 7 | 8 | import Foundation 9 | 10 | public protocol NetworkConfigurable { 11 | var baseURL: URL { get } 12 | var headers: [String: String] { get } 13 | var queryParameters: [String: String] { get } 14 | } 15 | 16 | public struct ApiDataNetworkConfig: NetworkConfigurable { 17 | public let baseURL: URL 18 | public let headers: [String: String] 19 | public let queryParameters: [String: String] 20 | 21 | public init(baseURL: URL, 22 | headers: [String: String] = [:], 23 | queryParameters: [String: String] = [:]) { 24 | self.baseURL = baseURL 25 | self.headers = headers 26 | self.queryParameters = queryParameters 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DevPods/Networking/Networking/Tests/Mocks/NetworkConfigurableMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkServiceMocks.swift 3 | // AppTests 4 | // 5 | // Created by Oleh Kudinov on 16.08.19. 6 | // 7 | 8 | import Foundation 9 | @testable import Networking 10 | 11 | class NetworkConfigurableMock: NetworkConfigurable { 12 | var baseURL: URL = URL(string: "https://mock.test.com")! 13 | var headers: [String: String] = [:] 14 | var queryParameters: [String: String] = [:] 15 | } 16 | -------------------------------------------------------------------------------- /DevPods/Networking/Networking/Tests/Mocks/NetworkSessionManagerMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkSessionManagerMock.swift 3 | // AppTests 4 | // 5 | // Created by Oleh Kudinov on 16.08.19. 6 | // 7 | 8 | import Foundation 9 | @testable import Networking 10 | 11 | struct NetworkSessionManagerMock: NetworkSessionManager { 12 | let response: HTTPURLResponse? 13 | let data: Data? 14 | let error: Error? 15 | 16 | func request(_ request: URLRequest, 17 | completion: @escaping CompletionHandler) -> NetworkCancellable { 18 | completion(data, response, error) 19 | return URLSessionDataTask() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /DevPods/Networking/README.md: -------------------------------------------------------------------------------- 1 | # Networking 2 | 3 | [![CI Status](https://img.shields.io/travis/olehkudinovolx/Networking.svg?style=flat)](https://travis-ci.org/olehkudinovolx/Networking) 4 | [![Version](https://img.shields.io/cocoapods/v/Networking.svg?style=flat)](https://cocoapods.org/pods/Networking) 5 | [![License](https://img.shields.io/cocoapods/l/Networking.svg?style=flat)](https://cocoapods.org/pods/Networking) 6 | [![Platform](https://img.shields.io/cocoapods/p/Networking.svg?style=flat)](https://cocoapods.org/pods/Networking) 7 | 8 | ## Example 9 | 10 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 11 | 12 | ## Requirements 13 | 14 | ## Installation 15 | 16 | Networking is available through [CocoaPods](https://cocoapods.org). To install 17 | it, simply add the following line to your Podfile: 18 | 19 | ```ruby 20 | pod 'Networking' 21 | ``` 22 | 23 | ## Author 24 | 25 | olehkudinovolx, oleh.kudinov@olx.com 26 | 27 | ## License 28 | 29 | Networking is available under the MIT license. See the LICENSE file for more info. 30 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'fastlane' 4 | gem 'rake' 5 | gem 'cocoapods' -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '12.4' 2 | 3 | workspace 'App.xcworkspace' 4 | project 'App.xcodeproj' 5 | 6 | def networking_pod 7 | pod 'Networking', :path => 'DevPods/Networking', :testspecs => ['Tests'] 8 | end 9 | 10 | def authentication_pod 11 | pod 'Authentication', :path => 'DevPods/Authentication' 12 | end 13 | 14 | def movies_search_pod 15 | pod 'MoviesSearch', :path => 'DevPods/MoviesSearch', :testspecs => ['Tests'] 16 | end 17 | 18 | def development_pods 19 | networking_pod 20 | authentication_pod 21 | movies_search_pod 22 | end 23 | 24 | target 'App' do 25 | use_frameworks! 26 | # Pods for App 27 | development_pods 28 | end 29 | 30 | target 'AppUITests' do 31 | use_frameworks! 32 | 33 | # Pods for testing 34 | development_pods 35 | end 36 | 37 | target 'Networking_Example' do 38 | use_frameworks! 39 | project 'DevPods/Networking/Example/Networking.xcodeproj' 40 | 41 | networking_pod 42 | end 43 | 44 | target 'Authentication_Example' do 45 | use_frameworks! 46 | project 'DevPods/Authentication/Example/Authentication.xcodeproj' 47 | 48 | authentication_pod 49 | end 50 | 51 | target 'MoviesSearch_Example' do 52 | use_frameworks! 53 | project 'DevPods/MoviesSearch/Example/MoviesSearch.xcodeproj' 54 | 55 | movies_search_pod 56 | end 57 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (4.9.1) 3 | - Authentication (0.1.0): 4 | - Alamofire (= 4.9.1) 5 | - iOSSnapshotTestCase (8.0.0): 6 | - iOSSnapshotTestCase/SwiftSupport (= 8.0.0) 7 | - iOSSnapshotTestCase/Core (8.0.0) 8 | - iOSSnapshotTestCase/SwiftSupport (8.0.0): 9 | - iOSSnapshotTestCase/Core 10 | - MoviesSearch (0.1.0): 11 | - Networking 12 | - MoviesSearch/Tests (0.1.0): 13 | - iOSSnapshotTestCase 14 | - Networking 15 | - Nimble 16 | - Quick 17 | - Networking (0.1.0) 18 | - Networking/Tests (0.1.0) 19 | - Nimble (9.2.1) 20 | - Quick (4.0.0) 21 | 22 | DEPENDENCIES: 23 | - Authentication (from `DevPods/Authentication`) 24 | - MoviesSearch (from `DevPods/MoviesSearch`) 25 | - MoviesSearch/Tests (from `DevPods/MoviesSearch`) 26 | - Networking (from `DevPods/Networking`) 27 | - Networking/Tests (from `DevPods/Networking`) 28 | 29 | SPEC REPOS: 30 | trunk: 31 | - Alamofire 32 | - iOSSnapshotTestCase 33 | - Nimble 34 | - Quick 35 | 36 | EXTERNAL SOURCES: 37 | Authentication: 38 | :path: DevPods/Authentication 39 | MoviesSearch: 40 | :path: DevPods/MoviesSearch 41 | Networking: 42 | :path: DevPods/Networking 43 | 44 | SPEC CHECKSUMS: 45 | Alamofire: 85e8a02c69d6020a0d734f6054870d7ecb75cf18 46 | Authentication: 0f4e10e049edb7aea6e77d73e66474058e330b61 47 | iOSSnapshotTestCase: a670511f9ee3829c2b9c23e6e68f315fd7b6790f 48 | MoviesSearch: 9c643ee0dd9d503686ae32d9a41418324f6cbddf 49 | Networking: d2f86022b8e0b2af29515584ee9d6c8251bfd46b 50 | Nimble: e7e615c0335ee4bf5b0d786685451e62746117d5 51 | Quick: 6473349e43b9271a8d43839d9ba1c442ed1b7ac4 52 | 53 | PODFILE CHECKSUM: ef9e0bc90230dd7922633146937fee28851b9839 54 | 55 | COCOAPODS: 1.8.4 56 | -------------------------------------------------------------------------------- /Pods/Alamofire/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/DispatchQueue+Alamofire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DispatchQueue+Alamofire.swift 3 | // 4 | // Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Dispatch 26 | import Foundation 27 | 28 | extension DispatchQueue { 29 | static var userInteractive: DispatchQueue { return DispatchQueue.global(qos: .userInteractive) } 30 | static var userInitiated: DispatchQueue { return DispatchQueue.global(qos: .userInitiated) } 31 | static var utility: DispatchQueue { return DispatchQueue.global(qos: .utility) } 32 | static var background: DispatchQueue { return DispatchQueue.global(qos: .background) } 33 | 34 | func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) { 35 | asyncAfter(deadline: .now() + delay, execute: closure) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Pods/Local Podspecs/Authentication.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Authentication", 3 | "version": "0.1.0", 4 | "summary": "A short description of Authentication.", 5 | "description": "TODO: Add long description of the pod here.", 6 | "homepage": "https://github.com/olehkudinovolx/Authentication", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "olehkudinovolx": "oleh.kudinov@olx.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com/olehkudinovolx/Authentication.git", 16 | "tag": "0.1.0" 17 | }, 18 | "platforms": { 19 | "ios": "12.4" 20 | }, 21 | "source_files": "Authentication/Module/**/*.{swift}", 22 | "resources": "Authentication/Module/**/*.{xcassets,json,storyboard,xib,xcdatamodeld}", 23 | "dependencies": { 24 | "Alamofire": [ 25 | "4.9.1" 26 | ] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Pods/Local Podspecs/MoviesSearch.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MoviesSearch", 3 | "version": "0.1.0", 4 | "summary": "A short description of MoviesSearch.", 5 | "description": "TODO: Add long description of the pod here.", 6 | "homepage": "https://github.com/olehkudinovolx/MoviesSearch", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "olehkudinovolx": "oleh.kudinov@olx.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com/olehkudinovolx/MoviesSearch.git", 16 | "tag": "0.1.0" 17 | }, 18 | "platforms": { 19 | "ios": "12.4" 20 | }, 21 | "source_files": "MoviesSearch/Module/**/*.{swift}", 22 | "resources": "MoviesSearch/Module/**/*.{xcassets,json,storyboard,xib,xcdatamodeld}", 23 | "dependencies": { 24 | "Networking": [ 25 | 26 | ] 27 | }, 28 | "weak_frameworks": "SwiftUI", 29 | "testspecs": [ 30 | { 31 | "name": "Tests", 32 | "test_type": "unit", 33 | "source_files": "MoviesSearch/Tests/**/*.{swift}", 34 | "dependencies": { 35 | "Quick": [ 36 | 37 | ], 38 | "Nimble": [ 39 | 40 | ], 41 | "iOSSnapshotTestCase": [ 42 | 43 | ] 44 | } 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /Pods/Local Podspecs/Networking.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Networking", 3 | "version": "0.1.0", 4 | "summary": "A short description of Networking.", 5 | "description": "TODO: Add long description of the pod here.", 6 | "homepage": "https://github.com/olehkudinovolx/Networking", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "olehkudinovolx": "oleh.kudinov@olx.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com/olehkudinovolx/Networking.git", 16 | "tag": "0.1.0" 17 | }, 18 | "platforms": { 19 | "ios": "12.4" 20 | }, 21 | "source_files": "Networking/Module/**/*.{swift}", 22 | "resources": "Networking/Module/**/*.{xcassets,json,storyboard,xib,xcdatamodeld}", 23 | "testspecs": [ 24 | { 25 | "name": "Tests", 26 | "test_type": "unit", 27 | "source_files": "Networking/Tests/**/*.{swift}" 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (4.9.1) 3 | - Authentication (0.1.0): 4 | - Alamofire (= 4.9.1) 5 | - iOSSnapshotTestCase (8.0.0): 6 | - iOSSnapshotTestCase/SwiftSupport (= 8.0.0) 7 | - iOSSnapshotTestCase/Core (8.0.0) 8 | - iOSSnapshotTestCase/SwiftSupport (8.0.0): 9 | - iOSSnapshotTestCase/Core 10 | - MoviesSearch (0.1.0): 11 | - Networking 12 | - MoviesSearch/Tests (0.1.0): 13 | - iOSSnapshotTestCase 14 | - Networking 15 | - Nimble 16 | - Quick 17 | - Networking (0.1.0) 18 | - Networking/Tests (0.1.0) 19 | - Nimble (9.2.1) 20 | - Quick (4.0.0) 21 | 22 | DEPENDENCIES: 23 | - Authentication (from `DevPods/Authentication`) 24 | - MoviesSearch (from `DevPods/MoviesSearch`) 25 | - MoviesSearch/Tests (from `DevPods/MoviesSearch`) 26 | - Networking (from `DevPods/Networking`) 27 | - Networking/Tests (from `DevPods/Networking`) 28 | 29 | SPEC REPOS: 30 | trunk: 31 | - Alamofire 32 | - iOSSnapshotTestCase 33 | - Nimble 34 | - Quick 35 | 36 | EXTERNAL SOURCES: 37 | Authentication: 38 | :path: DevPods/Authentication 39 | MoviesSearch: 40 | :path: DevPods/MoviesSearch 41 | Networking: 42 | :path: DevPods/Networking 43 | 44 | SPEC CHECKSUMS: 45 | Alamofire: 85e8a02c69d6020a0d734f6054870d7ecb75cf18 46 | Authentication: 0f4e10e049edb7aea6e77d73e66474058e330b61 47 | iOSSnapshotTestCase: a670511f9ee3829c2b9c23e6e68f315fd7b6790f 48 | MoviesSearch: 9c643ee0dd9d503686ae32d9a41418324f6cbddf 49 | Networking: d2f86022b8e0b2af29515584ee9d6c8251bfd46b 50 | Nimble: e7e615c0335ee4bf5b0d786685451e62746117d5 51 | Quick: 6473349e43b9271a8d43839d9ba1c442ed1b7ac4 52 | 53 | PODFILE CHECKSUM: ef9e0bc90230dd7922633146937fee28851b9839 54 | 55 | COCOAPODS: 1.8.4 56 | -------------------------------------------------------------------------------- /Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CwlCatchException.swift 3 | // CwlAssertionTesting 4 | // 5 | // Created by Matt Gallagher on 2016/01/10. 6 | // Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. 7 | // 8 | // Permission to use, copy, modify, and/or distribute this software for any 9 | // purpose with or without fee is hereby granted, provided that the above 10 | // copyright notice and this permission notice appear in all copies. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 15 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 18 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 | // 20 | 21 | import Foundation 22 | 23 | #if SWIFT_PACKAGE 24 | import CwlCatchExceptionSupport 25 | #endif 26 | 27 | private func catchReturnTypeConverter(_ type: T.Type, block: @escaping () -> Void) -> T? { 28 | return catchExceptionOfKind(type, block) as? T 29 | } 30 | 31 | extension NSException { 32 | public static func catchException(in block: @escaping () -> Void) -> Self? { 33 | return catchReturnTypeConverter(self, block: block) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m: -------------------------------------------------------------------------------- 1 | // 2 | // CwlCatchException.m 3 | // CwlAssertionTesting 4 | // 5 | // Created by Matt Gallagher on 2016/01/10. 6 | // Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. 7 | // 8 | // Permission to use, copy, modify, and/or distribute this software for any 9 | // purpose with or without fee is hereby granted, provided that the above 10 | // copyright notice and this permission notice appear in all copies. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 15 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 18 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 | // 20 | 21 | #import "CwlCatchException.h" 22 | 23 | NSException* __nullable catchExceptionOfKind(Class __nonnull type, void (^ __nonnull inBlock)(void)) { 24 | @try { 25 | inBlock(); 26 | } @catch (NSException *exception) { 27 | if ([exception isKindOfClass:type]) { 28 | return exception; 29 | } else { 30 | @throw; 31 | } 32 | } 33 | return nil; 34 | } 35 | -------------------------------------------------------------------------------- /Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h: -------------------------------------------------------------------------------- 1 | // 2 | // CwlCatchException.h 3 | // CwlCatchException 4 | // 5 | // Created by Matt Gallagher on 2016/01/10. 6 | // Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. 7 | // 8 | // Permission to use, copy, modify, and/or distribute this software for any 9 | // purpose with or without fee is hereby granted, provided that the above 10 | // copyright notice and this permission notice appear in all copies. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 15 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 18 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 | // 20 | 21 | #import 22 | 23 | NSException* __nullable catchExceptionOfKind(Class __nonnull type, void (^ __nonnull inBlock)(void)); 24 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift: -------------------------------------------------------------------------------- 1 | /// Protocol for the assertion handler that Nimble uses for all expectations. 2 | public protocol AssertionHandler { 3 | func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) 4 | } 5 | 6 | /// Global backing interface for assertions that Nimble creates. 7 | /// Defaults to a private test handler that passes through to XCTest. 8 | /// 9 | /// If XCTest is not available, you must assign your own assertion handler 10 | /// before using any matchers, otherwise Nimble will abort the program. 11 | /// 12 | /// @see AssertionHandler 13 | public var NimbleAssertionHandler: AssertionHandler = { () -> AssertionHandler in 14 | // swiftlint:disable:previous identifier_name 15 | return isXCTestAvailable() ? NimbleXCTestHandler() : NimbleXCTestUnavailableHandler() 16 | }() 17 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift: -------------------------------------------------------------------------------- 1 | /// AssertionDispatcher allows multiple AssertionHandlers to receive 2 | /// assertion messages. 3 | /// 4 | /// @warning Does not fully dispatch if one of the handlers raises an exception. 5 | /// This is possible with XCTest-based assertion handlers. 6 | /// 7 | public class AssertionDispatcher: AssertionHandler { 8 | let handlers: [AssertionHandler] 9 | 10 | public init(handlers: [AssertionHandler]) { 11 | self.handlers = handlers 12 | } 13 | 14 | public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { 15 | for handler in handlers { 16 | handler.assert(assertion, message: message, location: location) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift: -------------------------------------------------------------------------------- 1 | import Dispatch 2 | import class Foundation.NSObject 3 | import class Foundation.Thread 4 | 5 | /// "Global" state of Nimble is stored here. Only DSL functions should access / be aware of this 6 | /// class' existence 7 | internal class NimbleEnvironment: NSObject { 8 | static var activeInstance: NimbleEnvironment { 9 | get { 10 | let env = Thread.current.threadDictionary["NimbleEnvironment"] 11 | if let env = env as? NimbleEnvironment { 12 | return env 13 | } else { 14 | let newEnv = NimbleEnvironment() 15 | self.activeInstance = newEnv 16 | return newEnv 17 | } 18 | } 19 | set { 20 | Thread.current.threadDictionary["NimbleEnvironment"] = newValue 21 | } 22 | } 23 | 24 | // swiftlint:disable:next todo 25 | // TODO: eventually migrate the global to this environment value 26 | var assertionHandler: AssertionHandler { 27 | get { return NimbleAssertionHandler } 28 | set { NimbleAssertionHandler = newValue } 29 | } 30 | 31 | var suppressTVOSAssertionWarning: Bool = false 32 | var awaiter: Awaiter 33 | 34 | override init() { 35 | let timeoutQueue = DispatchQueue.global(qos: .userInitiated) 36 | awaiter = Awaiter( 37 | waitLock: AssertionWaitLock(), 38 | asyncQueue: .main, 39 | timeoutQueue: timeoutQueue 40 | ) 41 | 42 | super.init() 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift: -------------------------------------------------------------------------------- 1 | /// A Nimble matcher that succeeds when the actual value is greater than the expected value. 2 | public func beGreaterThan(_ expectedValue: T?) -> Predicate { 3 | let errorMessage = "be greater than <\(stringify(expectedValue))>" 4 | return Predicate.simple(errorMessage) { actualExpression in 5 | guard let actual = try actualExpression.evaluate(), let expected = expectedValue else { return .fail } 6 | 7 | return PredicateStatus(bool: actual > expected) 8 | } 9 | } 10 | 11 | public func >(lhs: Expectation, rhs: T) { 12 | lhs.to(beGreaterThan(rhs)) 13 | } 14 | 15 | #if canImport(Darwin) 16 | import enum Foundation.ComparisonResult 17 | 18 | /// A Nimble matcher that succeeds when the actual value is greater than the expected value. 19 | public func beGreaterThan(_ expectedValue: NMBComparable?) -> Predicate { 20 | let errorMessage = "be greater than <\(stringify(expectedValue))>" 21 | return Predicate.simple(errorMessage) { actualExpression in 22 | let actualValue = try actualExpression.evaluate() 23 | let matches = actualValue != nil 24 | && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedDescending 25 | return PredicateStatus(bool: matches) 26 | } 27 | } 28 | 29 | public func > (lhs: Expectation, rhs: NMBComparable?) { 30 | lhs.to(beGreaterThan(rhs)) 31 | } 32 | 33 | extension NMBPredicate { 34 | @objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBPredicate { 35 | return NMBPredicate { actualExpression in 36 | let expr = actualExpression.cast { $0 as? NMBComparable } 37 | return try beGreaterThan(expected).satisfies(expr).toObjectiveC() 38 | } 39 | } 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift: -------------------------------------------------------------------------------- 1 | /// A Nimble matcher that succeeds when the actual value is greater than 2 | /// or equal to the expected value. 3 | public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { 4 | let message = "be greater than or equal to <\(stringify(expectedValue))>" 5 | return Predicate.simple(message) { actualExpression in 6 | guard let actual = try actualExpression.evaluate(), let expected = expectedValue else { return .fail } 7 | 8 | return PredicateStatus(bool: actual >= expected) 9 | } 10 | } 11 | 12 | public func >=(lhs: Expectation, rhs: T) { 13 | lhs.to(beGreaterThanOrEqualTo(rhs)) 14 | } 15 | 16 | #if canImport(Darwin) 17 | import enum Foundation.ComparisonResult 18 | 19 | /// A Nimble matcher that succeeds when the actual value is greater than 20 | /// or equal to the expected value. 21 | public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { 22 | let message = "be greater than or equal to <\(stringify(expectedValue))>" 23 | return Predicate.simple(message) { actualExpression in 24 | let actualValue = try actualExpression.evaluate() 25 | let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedAscending 26 | return PredicateStatus(bool: matches) 27 | } 28 | } 29 | 30 | public func >=(lhs: Expectation, rhs: T) { 31 | lhs.to(beGreaterThanOrEqualTo(rhs)) 32 | } 33 | 34 | extension NMBPredicate { 35 | @objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBPredicate { 36 | return NMBPredicate { actualExpression in 37 | let expr = actualExpression.cast { $0 as? NMBComparable } 38 | return try beGreaterThanOrEqualTo(expected).satisfies(expr).toObjectiveC() 39 | } 40 | } 41 | } 42 | #endif 43 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift: -------------------------------------------------------------------------------- 1 | /// A Nimble matcher that succeeds when the actual value is the same instance 2 | /// as the expected instance. 3 | public func beIdenticalTo(_ expected: Any?) -> Predicate { 4 | return Predicate.define { actualExpression in 5 | let actual = try actualExpression.evaluate() as AnyObject? 6 | 7 | let bool = actual === (expected as AnyObject?) && actual !== nil 8 | return PredicateResult( 9 | bool: bool, 10 | message: .expectedCustomValueTo( 11 | "be identical to \(identityAsString(expected))", 12 | actual: "\(identityAsString(actual))" 13 | ) 14 | ) 15 | } 16 | } 17 | 18 | extension Expectation where T == Any { 19 | public static func === (lhs: Expectation, rhs: Any?) { 20 | lhs.to(beIdenticalTo(rhs)) 21 | } 22 | 23 | public static func !== (lhs: Expectation, rhs: Any?) { 24 | lhs.toNot(beIdenticalTo(rhs)) 25 | } 26 | } 27 | 28 | /// A Nimble matcher that succeeds when the actual value is the same instance 29 | /// as the expected instance. 30 | /// 31 | /// Alias for "beIdenticalTo". 32 | public func be(_ expected: Any?) -> Predicate { 33 | return beIdenticalTo(expected) 34 | } 35 | 36 | #if canImport(Darwin) 37 | import class Foundation.NSObject 38 | 39 | extension NMBPredicate { 40 | @objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBPredicate { 41 | return NMBPredicate { actualExpression in 42 | let aExpr = actualExpression.cast { $0 as Any? } 43 | return try beIdenticalTo(expected).satisfies(aExpr).toObjectiveC() 44 | } 45 | } 46 | } 47 | #endif 48 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Matchers/BeLessThan.swift: -------------------------------------------------------------------------------- 1 | /// A Nimble matcher that succeeds when the actual value is less than the expected value. 2 | public func beLessThan(_ expectedValue: T?) -> Predicate { 3 | let message = "be less than <\(stringify(expectedValue))>" 4 | return Predicate.simple(message) { actualExpression in 5 | guard let actual = try actualExpression.evaluate(), let expected = expectedValue else { return .fail } 6 | 7 | return PredicateStatus(bool: actual < expected) 8 | } 9 | } 10 | 11 | public func <(lhs: Expectation, rhs: T) { 12 | lhs.to(beLessThan(rhs)) 13 | } 14 | 15 | #if canImport(Darwin) 16 | import enum Foundation.ComparisonResult 17 | 18 | /// A Nimble matcher that succeeds when the actual value is less than the expected value. 19 | public func beLessThan(_ expectedValue: NMBComparable?) -> Predicate { 20 | let message = "be less than <\(stringify(expectedValue))>" 21 | return Predicate.simple(message) { actualExpression in 22 | let actualValue = try actualExpression.evaluate() 23 | let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedAscending 24 | return PredicateStatus(bool: matches) 25 | } 26 | } 27 | 28 | public func < (lhs: Expectation, rhs: NMBComparable?) { 29 | lhs.to(beLessThan(rhs)) 30 | } 31 | 32 | extension NMBPredicate { 33 | @objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBPredicate { 34 | return NMBPredicate { actualExpression in 35 | let expr = actualExpression.cast { $0 as? NMBComparable } 36 | return try beLessThan(expected).satisfies(expr).toObjectiveC() 37 | } 38 | } 39 | } 40 | #endif 41 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift: -------------------------------------------------------------------------------- 1 | /// A Nimble matcher that succeeds when the actual value is less than 2 | /// or equal to the expected value. 3 | public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { 4 | return Predicate.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in 5 | guard let actual = try actualExpression.evaluate(), let expected = expectedValue else { return .fail } 6 | 7 | return PredicateStatus(bool: actual <= expected) 8 | } 9 | } 10 | 11 | public func <=(lhs: Expectation, rhs: T) { 12 | lhs.to(beLessThanOrEqualTo(rhs)) 13 | } 14 | 15 | #if canImport(Darwin) 16 | import enum Foundation.ComparisonResult 17 | 18 | /// A Nimble matcher that succeeds when the actual value is less than 19 | /// or equal to the expected value. 20 | public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { 21 | return Predicate.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in 22 | let actualValue = try actualExpression.evaluate() 23 | let matches = actualValue.map { $0.NMB_compare(expectedValue) != .orderedDescending } ?? false 24 | return PredicateStatus(bool: matches) 25 | } 26 | } 27 | 28 | public func <=(lhs: Expectation, rhs: T) { 29 | lhs.to(beLessThanOrEqualTo(rhs)) 30 | } 31 | 32 | extension NMBPredicate { 33 | @objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBPredicate { 34 | return NMBPredicate { actualExpression in 35 | let expr = actualExpression.cast { $0 as? NMBComparable } 36 | return try beLessThanOrEqualTo(expected).satisfies(expr).toObjectiveC() 37 | } 38 | } 39 | } 40 | #endif 41 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Matchers/BeNil.swift: -------------------------------------------------------------------------------- 1 | /// A Nimble matcher that succeeds when the actual value is nil. 2 | public func beNil() -> Predicate { 3 | return Predicate.simpleNilable("be nil") { actualExpression in 4 | let actualValue = try actualExpression.evaluate() 5 | return PredicateStatus(bool: actualValue == nil) 6 | } 7 | } 8 | 9 | #if canImport(Darwin) 10 | import Foundation 11 | 12 | extension NMBPredicate { 13 | @objc public class func beNilMatcher() -> NMBPredicate { 14 | return NMBPredicate { actualExpression in 15 | return try beNil().satisfies(actualExpression).toObjectiveC() 16 | } 17 | } 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Matchers/BeVoid.swift: -------------------------------------------------------------------------------- 1 | /// A Nimble matcher that succeeds when the actual value is Void. 2 | public func beVoid() -> Predicate<()> { 3 | return Predicate.simpleNilable("be void") { actualExpression in 4 | let actualValue: ()? = try actualExpression.evaluate() 5 | return PredicateStatus(bool: actualValue != nil) 6 | } 7 | } 8 | 9 | extension Expectation where T == () { 10 | public static func == (lhs: Expectation<()>, rhs: ()) { 11 | lhs.to(beVoid()) 12 | } 13 | 14 | public static func != (lhs: Expectation<()>, rhs: ()) { 15 | lhs.toNot(beVoid()) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Matchers/Match.swift: -------------------------------------------------------------------------------- 1 | /// A Nimble matcher that succeeds when the actual string satisfies the regular expression 2 | /// described by the expected string. 3 | public func match(_ expectedValue: String?) -> Predicate { 4 | return Predicate.simple("match <\(stringify(expectedValue))>") { actualExpression in 5 | guard let actual = try actualExpression.evaluate(), let regexp = expectedValue else { return .fail } 6 | 7 | let bool = actual.range(of: regexp, options: .regularExpression) != nil 8 | return PredicateStatus(bool: bool) 9 | } 10 | } 11 | 12 | #if canImport(Darwin) 13 | import class Foundation.NSString 14 | 15 | extension NMBPredicate { 16 | @objc public class func matchMatcher(_ expected: NSString) -> NMBPredicate { 17 | return NMBPredicate { actualExpression in 18 | let actual = actualExpression.cast { $0 as? String } 19 | return try match(expected.description).satisfies(actual).toObjectiveC() 20 | } 21 | } 22 | } 23 | #endif 24 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Matchers/ToSucceed.swift: -------------------------------------------------------------------------------- 1 | /** 2 | Used by the `toSucceed` matcher. 3 | 4 | This is the return type for the closure. 5 | */ 6 | public enum ToSucceedResult { 7 | case succeeded 8 | case failed(reason: String) 9 | } 10 | 11 | /** 12 | A Nimble matcher that takes in a closure for validation. 13 | 14 | Return `.succeeded` when the validation succeeds. 15 | Return `.failed` with a failure reason when the validation fails. 16 | */ 17 | public func succeed() -> Predicate<() -> ToSucceedResult> { 18 | return Predicate.define { actualExpression in 19 | let optActual = try actualExpression.evaluate() 20 | guard let actual = optActual else { 21 | return PredicateResult(status: .fail, message: .fail("expected a closure, got ")) 22 | } 23 | 24 | switch actual() { 25 | case .succeeded: 26 | return PredicateResult( 27 | bool: true, 28 | message: .expectedCustomValueTo("succeed", actual: "") 29 | ) 30 | case .failed(let reason): 31 | return PredicateResult( 32 | bool: false, 33 | message: .expectedCustomValueTo("succeed", actual: " because <\(reason)>") 34 | ) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Nimble.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | 6 | #if TARGET_OS_OSX || TARGET_OS_IOS 7 | #import 8 | #import 9 | #endif 10 | 11 | FOUNDATION_EXPORT double NimbleVersionNumber; 12 | FOUNDATION_EXPORT const unsigned char NimbleVersionString[]; 13 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Utils/DispatchTimeInterval.swift: -------------------------------------------------------------------------------- 1 | import Dispatch 2 | 3 | #if canImport(CDispatch) 4 | import CDispatch 5 | #endif 6 | 7 | extension DispatchTimeInterval { 8 | // ** Note: We cannot simply divide the time interval because DispatchTimeInterval associated value type is Int 9 | var divided: DispatchTimeInterval { 10 | switch self { 11 | case let .seconds(val): return val < 2 ? .milliseconds(Int(Float(val)/2*1000)) : .seconds(val/2) 12 | case let .milliseconds(val): return .milliseconds(val/2) 13 | case let .microseconds(val): return .microseconds(val/2) 14 | case let .nanoseconds(val): return .nanoseconds(val/2) 15 | case .never: return .never 16 | @unknown default: fatalError("Unknown DispatchTimeInterval value") 17 | } 18 | } 19 | 20 | var description: String { 21 | switch self { 22 | case let .seconds(val): return val == 1 ? "\(Float(val)) second" : "\(Float(val)) seconds" 23 | case let .milliseconds(val): return "\(Float(val)/1_000) seconds" 24 | case let .microseconds(val): return "\(Float(val)/1_000_000) seconds" 25 | case let .nanoseconds(val): return "\(Float(val)/1_000_000_000) seconds" 26 | default: fatalError("Unknown DispatchTimeInterval value") 27 | } 28 | } 29 | } 30 | 31 | #if canImport(Foundation) 32 | import typealias Foundation.TimeInterval 33 | 34 | extension TimeInterval { 35 | var dispatchInterval: DispatchTimeInterval { 36 | let microseconds = Int64(self * TimeInterval(USEC_PER_SEC)) 37 | // perhaps use nanoseconds, though would more often be > Int.max 38 | return microseconds < Int.max ? .microseconds(Int(microseconds)) : .seconds(Int(self)) 39 | } 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Utils/Errors.swift: -------------------------------------------------------------------------------- 1 | // Generic 2 | 3 | internal func messageForError( 4 | postfixMessageVerb: String = "throw", 5 | actualError: Error?, 6 | error: T? = nil, 7 | errorType: T.Type? = nil, 8 | closure: ((T) -> Void)? = nil 9 | ) -> ExpectationMessage { 10 | var rawMessage = "\(postfixMessageVerb) error" 11 | 12 | if let error = error { 13 | rawMessage += " <\(error)>" 14 | } else if errorType != nil || closure != nil { 15 | rawMessage += " from type <\(T.self)>" 16 | } 17 | if closure != nil { 18 | rawMessage += " that satisfies block" 19 | } 20 | if error == nil && errorType == nil && closure == nil { 21 | rawMessage = "\(postfixMessageVerb) any error" 22 | } 23 | 24 | let actual: String 25 | if let actualError = actualError { 26 | actual = "<\(actualError)>" 27 | } else { 28 | actual = "no error" 29 | } 30 | 31 | return .expectedCustomValueTo(rawMessage, actual: actual) 32 | } 33 | 34 | internal func errorMatchesExpectedError( 35 | _ actualError: Error, 36 | expectedError: T) -> Bool { 37 | return actualError._domain == expectedError._domain 38 | && actualError._code == expectedError._code 39 | } 40 | 41 | // Non-generic 42 | 43 | internal func messageForError( 44 | actualError: Error?, 45 | closure: ((Error) -> Void)? 46 | ) -> ExpectationMessage { 47 | var rawMessage = "throw error" 48 | 49 | if closure != nil { 50 | rawMessage += " that satisfies block" 51 | } else { 52 | rawMessage = "throw any error" 53 | } 54 | 55 | let actual: String 56 | if let actualError = actualError { 57 | actual = "<\(actualError)>" 58 | } else { 59 | actual = "no error" 60 | } 61 | 62 | return .expectedCustomValueTo(rawMessage, actual: actual) 63 | } 64 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/Nimble/Utils/SourceLocation.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // Ideally we would always use `StaticString` as the type for tracking the file name 4 | // that expectations originate from, for consistency with `assert` etc. from the 5 | // stdlib, and because recent versions of the XCTest overlay require `StaticString` 6 | // when calling `XCTFail`. Under the Objective-C runtime (i.e. building on Mac), we 7 | // have to use `String` instead because StaticString can't be generated from Objective-C 8 | #if SWIFT_PACKAGE 9 | public typealias FileString = StaticString 10 | #else 11 | public typealias FileString = String 12 | #endif 13 | 14 | public final class SourceLocation: NSObject { 15 | public let file: FileString 16 | public let line: UInt 17 | 18 | override init() { 19 | file = "Unknown File" 20 | line = 0 21 | } 22 | 23 | init(file: FileString, line: UInt) { 24 | self.file = file 25 | self.line = line 26 | } 27 | 28 | override public var description: String { 29 | return "\(file):\(line)" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface NMBExceptionCapture : NSObject 5 | 6 | - (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally; 7 | - (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock NS_SWIFT_NAME(tryBlock(_:)); 8 | 9 | @end 10 | 11 | typedef void(^NMBSourceCallbackBlock)(BOOL successful); 12 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m: -------------------------------------------------------------------------------- 1 | #import "NMBExceptionCapture.h" 2 | 3 | @interface NMBExceptionCapture () 4 | @property (nonatomic, copy) void(^ _Nullable handler)(NSException * _Nullable); 5 | @property (nonatomic, copy) void(^ _Nullable finally)(void); 6 | @end 7 | 8 | @implementation NMBExceptionCapture 9 | 10 | - (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally { 11 | self = [super init]; 12 | if (self) { 13 | self.handler = handler; 14 | self.finally = finally; 15 | } 16 | return self; 17 | } 18 | 19 | - (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock { 20 | @try { 21 | unsafeBlock(); 22 | } 23 | @catch (NSException *exception) { 24 | if (self.handler) { 25 | self.handler(exception); 26 | } 27 | } 28 | @finally { 29 | if (self.finally) { 30 | self.finally(); 31 | } 32 | } 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/NimbleObjectiveC/NMBStringify.h: -------------------------------------------------------------------------------- 1 | @class NSString; 2 | 3 | /** 4 | * Returns a string appropriate for displaying in test output 5 | * from the provided value. 6 | * 7 | * @param anyObject A value that will show up in a test's output. 8 | * 9 | * @return The string that is returned can be 10 | * customized per type by conforming a type to the `TestOutputStringConvertible` 11 | * protocol. When stringifying a non-`TestOutputStringConvertible` type, this 12 | * function will return the value's debug description and then its 13 | * normal description if available and in that order. Otherwise it 14 | * will return the result of constructing a string from the value. 15 | * 16 | * @see `TestOutputStringConvertible` 17 | */ 18 | extern NSString *_Nonnull NMBStringify(id _Nullable anyObject) __attribute__((warn_unused_result)); 19 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/NimbleObjectiveC/NMBStringify.m: -------------------------------------------------------------------------------- 1 | #import "NMBStringify.h" 2 | 3 | #if __has_include("Nimble-Swift.h") 4 | #import "Nimble-Swift.h" 5 | #else 6 | #import 7 | #endif 8 | 9 | NSString *_Nonnull NMBStringify(id _Nullable anyObject) { 10 | return [NMBStringer stringify:anyObject]; 11 | } 12 | -------------------------------------------------------------------------------- /Pods/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #if __has_include("Nimble-Swift.h") 4 | #import "Nimble-Swift.h" 5 | #else 6 | #import 7 | #endif 8 | 9 | #pragma mark - Private 10 | 11 | @implementation XCTestObservationCenter (Register) 12 | 13 | + (void)load { 14 | [[XCTestObservationCenter sharedTestObservationCenter] addTestObserver:[CurrentTestCaseTracker sharedInstance]]; 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/Behavior.swift: -------------------------------------------------------------------------------- 1 | /// A `Behavior` encapsulates a set of examples that can be re-used in several locations using the `itBehavesLike` 2 | /// function with a context instance of the generic type. 3 | open class Behavior { 4 | 5 | /** 6 | Override this variable if you want to provide custom name for this example group. 7 | */ 8 | open class var name: String { return String(describing: self) } 9 | 10 | /** 11 | Override this method in your behavior to define a set of reusable examples. 12 | 13 | This behaves just like an example group defines using `describe` or `context`--it may contain any number of `beforeEach` 14 | and `afterEach` closures, as well as any number of examples (defined using `it`). 15 | 16 | - parameter aContext: A closure that, when evaluated, returns a `Context` instance that provide the information on the subject. 17 | */ 18 | open class func spec(_ aContext: @escaping () -> Context) {} 19 | } 20 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/Callsite.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | #if canImport(Darwin) 4 | // swiftlint:disable type_name 5 | @objcMembers 6 | public class _CallsiteBase: NSObject {} 7 | #else 8 | public class _CallsiteBase: NSObject {} 9 | // swiftlint:enable type_name 10 | #endif 11 | 12 | // Ideally we would always use `StaticString` as the type for tracking the file name 13 | // in which an example is defined, for consistency with `assert` etc. from the 14 | // stdlib, and because recent versions of the XCTest overlay require `StaticString` 15 | // when calling `XCTFail`. Under the Objective-C runtime (i.e. building on macOS), we 16 | // have to use `String` instead because StaticString can't be generated from Objective-C 17 | #if SWIFT_PACKAGE 18 | public typealias FileString = StaticString 19 | #else 20 | public typealias FileString = String 21 | #endif 22 | 23 | /** 24 | An object encapsulating the file and line number at which 25 | a particular example is defined. 26 | */ 27 | final public class Callsite: _CallsiteBase { 28 | /** 29 | The absolute path of the file in which an example is defined. 30 | */ 31 | public let file: FileString 32 | 33 | /** 34 | The line number on which an example is defined. 35 | */ 36 | public let line: UInt 37 | 38 | internal init(file: FileString, line: UInt) { 39 | self.file = file 40 | self.line = line 41 | } 42 | } 43 | 44 | extension Callsite { 45 | /** 46 | Returns a boolean indicating whether two Callsite objects are equal. 47 | If two callsites are in the same file and on the same line, they must be equal. 48 | */ 49 | @nonobjc public static func == (lhs: Callsite, rhs: Callsite) -> Bool { 50 | return String(describing: lhs.file) == String(describing: rhs.file) && lhs.line == rhs.line 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/ErrorUtility.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | internal func raiseError(_ message: String) -> Never { 4 | #if canImport(Darwin) 5 | NSException(name: .internalInconsistencyException, reason: message, userInfo: nil).raise() 6 | #endif 7 | 8 | // This won't be reached when ObjC is available and the exception above is raisd 9 | fatalError(message) 10 | } 11 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/ExampleMetadata.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | #if canImport(Darwin) 4 | // swiftlint:disable type_name 5 | @objcMembers 6 | public class _ExampleMetadataBase: NSObject {} 7 | #else 8 | public class _ExampleMetadataBase: NSObject {} 9 | // swiftlint:enable type_name 10 | #endif 11 | 12 | /** 13 | A class that encapsulates information about an example, 14 | including the index at which the example was executed, as 15 | well as the example itself. 16 | */ 17 | final public class ExampleMetadata: _ExampleMetadataBase { 18 | /** 19 | The example for which this metadata was collected. 20 | */ 21 | public let example: Example 22 | 23 | /** 24 | The index at which this example was executed in the 25 | test suite. 26 | */ 27 | public let exampleIndex: Int 28 | 29 | internal init(example: Example, exampleIndex: Int) { 30 | self.example = example 31 | self.exampleIndex = exampleIndex 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/Filter.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | #if canImport(Darwin) 4 | // swiftlint:disable type_name 5 | @objcMembers 6 | public class _FilterBase: NSObject {} 7 | #else 8 | public class _FilterBase: NSObject {} 9 | // swiftlint:enable type_name 10 | #endif 11 | 12 | /** 13 | A mapping of string keys to booleans that can be used to 14 | filter examples or example groups. For example, a "focused" 15 | example would have the flags [Focused: true]. 16 | */ 17 | public typealias FilterFlags = [String: Bool] 18 | 19 | /** 20 | A namespace for filter flag keys, defined primarily to make the 21 | keys available in Objective-C. 22 | */ 23 | final public class Filter: _FilterBase { 24 | /** 25 | Example and example groups with [Focused: true] are included in test runs, 26 | excluding all other examples without this flag. Use this to only run one or 27 | two tests that you're currently focusing on. 28 | */ 29 | public class var focused: String { 30 | return "focused" 31 | } 32 | 33 | /** 34 | Example and example groups with [Pending: true] are excluded from test runs. 35 | Use this to temporarily suspend examples that you know do not pass yet. 36 | */ 37 | public class var pending: String { 38 | return "pending" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/Hooks/Closures.swift: -------------------------------------------------------------------------------- 1 | // MARK: Example Hooks 2 | 3 | /** 4 | A closure executed before an example is run. 5 | */ 6 | public typealias BeforeExampleClosure = () -> Void 7 | 8 | /** 9 | A closure executed before an example is run. The closure is given example metadata, 10 | which contains information about the example that is about to be run. 11 | */ 12 | public typealias BeforeExampleWithMetadataClosure = (_ exampleMetadata: ExampleMetadata) -> Void 13 | 14 | /** 15 | A closure executed after an example is run. 16 | */ 17 | public typealias AfterExampleClosure = BeforeExampleClosure 18 | 19 | /** 20 | A closure executed after an example is run. The closure is given example metadata, 21 | which contains information about the example that has just finished running. 22 | */ 23 | public typealias AfterExampleWithMetadataClosure = BeforeExampleWithMetadataClosure 24 | 25 | // MARK: Suite Hooks 26 | 27 | /** 28 | A closure executed before any examples are run. 29 | */ 30 | public typealias BeforeSuiteClosure = () -> Void 31 | 32 | /** 33 | A closure executed after all examples have finished running. 34 | */ 35 | public typealias AfterSuiteClosure = BeforeSuiteClosure 36 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/Hooks/ExampleHooks.swift: -------------------------------------------------------------------------------- 1 | /** 2 | A container for closures to be executed before and after each example. 3 | */ 4 | final internal class ExampleHooks { 5 | internal var befores: [BeforeExampleWithMetadataClosure] = [] 6 | internal var afters: [AfterExampleWithMetadataClosure] = [] 7 | internal var phase: HooksPhase = .nothingExecuted 8 | 9 | internal func appendBefore(_ closure: @escaping BeforeExampleWithMetadataClosure) { 10 | befores.append(closure) 11 | } 12 | 13 | internal func appendBefore(_ closure: @escaping BeforeExampleClosure) { 14 | befores.append { (_: ExampleMetadata) in closure() } 15 | } 16 | 17 | internal func appendAfter(_ closure: @escaping AfterExampleWithMetadataClosure) { 18 | afters.append(closure) 19 | } 20 | 21 | internal func appendAfter(_ closure: @escaping AfterExampleClosure) { 22 | afters.append { (_: ExampleMetadata) in closure() } 23 | } 24 | 25 | internal func executeBefores(_ exampleMetadata: ExampleMetadata) { 26 | phase = .beforesExecuting 27 | for before in befores { 28 | before(exampleMetadata) 29 | } 30 | 31 | phase = .beforesFinished 32 | } 33 | 34 | internal func executeAfters(_ exampleMetadata: ExampleMetadata) { 35 | phase = .aftersExecuting 36 | for after in afters { 37 | after(exampleMetadata) 38 | } 39 | 40 | phase = .aftersFinished 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/Hooks/HooksPhase.swift: -------------------------------------------------------------------------------- 1 | /** 2 | A description of the execution cycle of the current example with 3 | respect to the hooks of that example. 4 | */ 5 | internal enum HooksPhase { 6 | case nothingExecuted 7 | case beforesExecuting 8 | case beforesFinished 9 | case aftersExecuting 10 | case aftersFinished 11 | } 12 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/Hooks/SuiteHooks.swift: -------------------------------------------------------------------------------- 1 | /** 2 | A container for closures to be executed before and after all examples. 3 | */ 4 | final internal class SuiteHooks { 5 | internal var befores: [BeforeSuiteClosure] = [] 6 | internal var afters: [AfterSuiteClosure] = [] 7 | internal var phase: HooksPhase = .nothingExecuted 8 | 9 | internal func appendBefore(_ closure: @escaping BeforeSuiteClosure) { 10 | befores.append(closure) 11 | } 12 | 13 | internal func appendAfter(_ closure: @escaping AfterSuiteClosure) { 14 | afters.append(closure) 15 | } 16 | 17 | internal func executeBefores() { 18 | phase = .beforesExecuting 19 | for before in befores { 20 | before() 21 | } 22 | phase = .beforesFinished 23 | } 24 | 25 | internal func executeAfters() { 26 | phase = .aftersExecuting 27 | for after in afters { 28 | after() 29 | } 30 | phase = .aftersFinished 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift: -------------------------------------------------------------------------------- 1 | #if canImport(Darwin) 2 | 3 | import Foundation 4 | 5 | extension Bundle { 6 | 7 | /** 8 | Locates the first bundle with a '.xctest' file extension. 9 | */ 10 | internal static var currentTestBundle: Bundle? { 11 | return allBundles.first { $0.bundlePath.hasSuffix(".xctest") } 12 | } 13 | 14 | /** 15 | Return the module name of the bundle. 16 | Uses the bundle filename and transform it to match Xcode's transformation. 17 | Module name has to be a valid "C99 extended identifier". 18 | */ 19 | internal var moduleName: String { 20 | let fileName = bundleURL.fileName 21 | return fileName.c99ExtendedIdentifier 22 | } 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/QuickTestSuite.swift: -------------------------------------------------------------------------------- 1 | #if canImport(Darwin) 2 | 3 | import XCTest 4 | 5 | /** 6 | This protocol defines the role of an object that builds test suites. 7 | */ 8 | internal protocol QuickTestSuiteBuilder { 9 | 10 | /** 11 | Construct a `QuickTestSuite` instance with the appropriate test cases added as tests. 12 | 13 | Subsequent calls to this method should return equivalent test suites. 14 | */ 15 | func buildTestSuite() -> QuickTestSuite 16 | 17 | } 18 | 19 | /** 20 | A base class for a class cluster of Quick test suites, that should correctly 21 | build dynamic test suites for XCTest to execute. 22 | */ 23 | public class QuickTestSuite: XCTestSuite { 24 | 25 | private static var builtTestSuites: Set = Set() 26 | 27 | /** 28 | Construct a test suite for a specific, selected subset of test cases (rather 29 | than the default, which as all test cases). 30 | 31 | If this method is called multiple times for the same test case class, e.g.. 32 | 33 | FooSpec/testFoo 34 | FooSpec/testBar 35 | 36 | It is expected that the first call should return a valid test suite, and 37 | all subsequent calls should return `nil`. 38 | */ 39 | @objc 40 | public static func selectedTestSuite(forTestCaseWithName name: String) -> QuickTestSuite? { 41 | guard let builder = QuickSelectedTestSuiteBuilder(forTestCaseWithName: name) else { return nil } 42 | 43 | let (inserted, _) = builtTestSuites.insert(builder.testSuiteClassName) 44 | if inserted { 45 | return builder.buildTestSuite() 46 | } else { 47 | return nil 48 | } 49 | } 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/String+C99ExtendedIdentifier.swift: -------------------------------------------------------------------------------- 1 | #if canImport(Darwin) 2 | import Foundation 3 | 4 | extension String { 5 | private static var invalidCharacters: CharacterSet = { 6 | var invalidCharacters = CharacterSet() 7 | 8 | let invalidCharacterSets: [CharacterSet] = [ 9 | .whitespacesAndNewlines, 10 | .illegalCharacters, 11 | .controlCharacters, 12 | .punctuationCharacters, 13 | .nonBaseCharacters, 14 | .symbols, 15 | ] 16 | 17 | for invalidSet in invalidCharacterSets { 18 | invalidCharacters.formUnion(invalidSet) 19 | } 20 | 21 | return invalidCharacters 22 | }() 23 | 24 | internal var c99ExtendedIdentifier: String { 25 | let validComponents = components(separatedBy: String.invalidCharacters) 26 | let result = validComponents.joined(separator: "_") 27 | 28 | return result.isEmpty ? "_" : result 29 | } 30 | } 31 | 32 | /// Extension methods or properties for NSObject subclasses are invisible from 33 | /// the Objective-C runtime on static linking unless the consumers add `-ObjC` 34 | /// linker flag, so let's make a wrapper class to mitigate that situation. 35 | /// 36 | /// See: https://github.com/Quick/Quick/issues/785 and https://github.com/Quick/Quick/pull/803 37 | @objc 38 | class QCKObjCStringUtils: NSObject { 39 | override private init() {} 40 | 41 | @objc 42 | static func c99ExtendedIdentifier(from string: String) -> String { 43 | return string.c99ExtendedIdentifier 44 | } 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/Quick/URL+FileName.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension URL { 4 | 5 | /** 6 | Returns the path file name without file extension. 7 | */ 8 | var fileName: String { 9 | return self.deletingPathExtension().lastPathComponent 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/QuickObjCRuntime/QuickSpecBase.m: -------------------------------------------------------------------------------- 1 | #import "QuickSpecBase.h" 2 | 3 | #pragma mark - _QuickSpecBase 4 | 5 | @implementation _QuickSpecBase 6 | 7 | - (instancetype)init { 8 | self = [super initWithInvocation: nil]; 9 | return self; 10 | } 11 | 12 | /** 13 | Invocations for each test method in the test case. QuickSpec overrides this method to define a 14 | new method for each example defined in +[QuickSpec spec]. 15 | 16 | @return An array of invocations that execute the newly defined example methods. 17 | */ 18 | + (NSArray *)testInvocations { 19 | NSArray *selectors = [self _qck_testMethodSelectors]; 20 | NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:selectors.count]; 21 | 22 | for (NSString *selectorString in selectors) { 23 | SEL selector = NSSelectorFromString(selectorString); 24 | NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; 25 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; 26 | invocation.selector = selector; 27 | 28 | [invocations addObject:invocation]; 29 | } 30 | 31 | return invocations; 32 | } 33 | 34 | + (NSArray *)_qck_testMethodSelectors { 35 | return @[]; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/QuickObjCRuntime/include/QuickObjCRuntime.h: -------------------------------------------------------------------------------- 1 | #if __has_include("QuickSpecBase.h") 2 | #import "QuickSpecBase.h" 3 | #else 4 | #import 5 | #endif 6 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/QuickObjCRuntime/include/QuickSpecBase.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface _QuickSpecBase : XCTestCase 5 | + (NSArray *)_qck_testMethodSelectors; 6 | - (instancetype)init NS_DESIGNATED_INITIALIZER; 7 | @end 8 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class Configuration; 4 | 5 | /** 6 | Subclass QuickConfiguration and override the +[QuickConfiguration configure:] 7 | method in order to configure how Quick behaves when running specs, or to define 8 | shared examples that are used across spec files. 9 | */ 10 | @interface QuickConfiguration : NSObject 11 | 12 | /** 13 | This method is executed on each subclass of this class before Quick runs 14 | any examples. You may override this method on as many subclasses as you like, but 15 | there is no guarantee as to the order in which these methods are executed. 16 | 17 | You can override this method in order to: 18 | 19 | 1. Configure how Quick behaves, by modifying properties on the Configuration object. 20 | Setting the same properties in several methods has undefined behavior. 21 | 22 | 2. Define shared examples using `sharedExamples`. 23 | 24 | @param configuration A mutable object that is used to configure how Quick behaves on 25 | a framework level. For details on all the options, see the 26 | documentation in Configuration.swift. 27 | */ 28 | + (void)configure:(Configuration *)configuration; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m: -------------------------------------------------------------------------------- 1 | #import "QuickConfiguration.h" 2 | #import 3 | 4 | #if __has_include("Quick-Swift.h") 5 | #import "Quick-Swift.h" 6 | #else 7 | #import 8 | #endif 9 | 10 | @implementation QuickConfiguration 11 | 12 | #pragma mark - Object Lifecycle 13 | 14 | /** 15 | QuickConfiguration is not meant to be instantiated; it merely provides a hook 16 | for users to configure how Quick behaves. Raise an exception if an instance of 17 | QuickConfiguration is created. 18 | */ 19 | - (instancetype)init { 20 | NSString *className = NSStringFromClass([self class]); 21 | NSString *selectorName = NSStringFromSelector(@selector(configure:)); 22 | [NSException raise:NSInternalInconsistencyException 23 | format:@"%@ is not meant to be instantiated; " 24 | @"subclass %@ and override %@ to configure Quick.", 25 | className, className, selectorName]; 26 | return nil; 27 | } 28 | 29 | #pragma mark - NSObject Overrides 30 | 31 | /** 32 | Hook into when QuickConfiguration is initialized in the runtime in order to 33 | call +[QuickConfiguration configure:] on each of its subclasses. 34 | */ 35 | + (void)initialize { 36 | // Only enumerate over the subclasses of QuickConfiguration, not any of its subclasses. 37 | if ([self class] == [QuickConfiguration class]) { 38 | World *world = [World sharedWorld]; 39 | [self configureSubclassesIfNeededWithWorld:world]; 40 | } 41 | } 42 | 43 | #pragma mark - Public Interface 44 | 45 | + (void)configure:(Configuration *)configuration { } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/QuickObjectiveC/Quick.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | //! Project version number for Quick. 4 | FOUNDATION_EXPORT double QuickVersionNumber; 5 | 6 | //! Project version string for Quick. 7 | FOUNDATION_EXPORT const unsigned char QuickVersionString[]; 8 | 9 | #import 10 | #import 11 | #import 12 | -------------------------------------------------------------------------------- /Pods/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #if __has_include("Quick-Swift.h") 5 | #import "Quick-Swift.h" 6 | #else 7 | #import 8 | #endif 9 | 10 | @interface XCTestSuite (QuickTestSuiteBuilder) 11 | @end 12 | 13 | @implementation XCTestSuite (QuickTestSuiteBuilder) 14 | 15 | /** 16 | In order to ensure we can correctly build dynamic test suites, we need to 17 | replace some of the default test suite constructors. 18 | */ 19 | + (void)load { 20 | Method testCaseWithName = class_getClassMethod(self, @selector(testSuiteForTestCaseWithName:)); 21 | Method hooked_testCaseWithName = class_getClassMethod(self, @selector(qck_hooked_testSuiteForTestCaseWithName:)); 22 | method_exchangeImplementations(testCaseWithName, hooked_testCaseWithName); 23 | } 24 | 25 | /** 26 | The `+testSuiteForTestCaseWithName:` method is called when a specific test case 27 | class is run from the Xcode test navigator. If the built test suite is `nil`, 28 | Xcode will not run any tests for that test case. 29 | 30 | Given if the following test case class is run from the Xcode test navigator: 31 | 32 | FooSpec 33 | testFoo 34 | testBar 35 | 36 | XCTest will invoke this once per test case, with test case names following this format: 37 | 38 | FooSpec/testFoo 39 | FooSpec/testBar 40 | */ 41 | + (nullable instancetype)qck_hooked_testSuiteForTestCaseWithName:(nonnull NSString *)name { 42 | return [QuickTestSuite selectedTestSuiteForTestCaseWithName:name]; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 4.9.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Alamofire : NSObject 3 | @end 4 | @implementation PodsDummy_Alamofire 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double AlamofireVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char AlamofireVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire.modulemap: -------------------------------------------------------------------------------- 1 | framework module Alamofire { 2 | umbrella header "Alamofire-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Alamofire 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Alamofire 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Authentication/Authentication-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Authentication/Authentication-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Authentication : NSObject 3 | @end 4 | @implementation PodsDummy_Authentication 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Authentication/Authentication-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Authentication/Authentication-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double AuthenticationVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char AuthenticationVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Authentication/Authentication.modulemap: -------------------------------------------------------------------------------- 1 | framework module Authentication { 2 | umbrella header "Authentication-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Authentication/Authentication.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Authentication 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../DevPods/Authentication 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 12 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MoviesSearch/MoviesSearch-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MoviesSearch/MoviesSearch-Unit-Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleIdentifier 8 | ${PRODUCT_BUNDLE_IDENTIFIER} 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | ${PRODUCT_NAME} 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MoviesSearch/MoviesSearch-Unit-Tests-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MoviesSearch/MoviesSearch-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_MoviesSearch : NSObject 3 | @end 4 | @implementation PodsDummy_MoviesSearch 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MoviesSearch/MoviesSearch-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MoviesSearch/MoviesSearch-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double MoviesSearchVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char MoviesSearchVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MoviesSearch/MoviesSearch.modulemap: -------------------------------------------------------------------------------- 1 | framework module MoviesSearch { 2 | umbrella header "MoviesSearch-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MoviesSearch/MoviesSearch.unit-tests.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch" "${PODS_CONFIGURATION_BUILD_DIR}/Networking" "${PODS_CONFIGURATION_BUILD_DIR}/Nimble" "${PODS_CONFIGURATION_BUILD_DIR}/Quick" "${PODS_CONFIGURATION_BUILD_DIR}/iOSSnapshotTestCase" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_LDFLAGS = $(inherited) -ObjC -framework "FBSnapshotTestCase" -framework "Foundation" -framework "MoviesSearch" -framework "Networking" -framework "Nimble" -framework "QuartzCore" -framework "Quick" -framework "UIKit" -framework "XCTest" -weak_framework "SwiftUI" -weak_framework "XCTest" 5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../DevPods/MoviesSearch 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MoviesSearch/MoviesSearch.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Networking" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_LDFLAGS = $(inherited) -weak_framework "SwiftUI" 5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../DevPods/MoviesSearch 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Networking/Networking-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Networking/Networking-Unit-Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleIdentifier 8 | ${PRODUCT_BUNDLE_IDENTIFIER} 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | ${PRODUCT_NAME} 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Networking/Networking-Unit-Tests-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Networking/Networking-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Networking : NSObject 3 | @end 4 | @implementation PodsDummy_Networking 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Networking/Networking-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Networking/Networking-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double NetworkingVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char NetworkingVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Networking/Networking.modulemap: -------------------------------------------------------------------------------- 1 | framework module Networking { 2 | umbrella header "Networking-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Networking/Networking.unit-tests.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Networking" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_LDFLAGS = $(inherited) -ObjC -framework "Networking" 5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../DevPods/Networking 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Networking/Networking.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Networking 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../DevPods/Networking 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Nimble/Nimble-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 9.2.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Nimble/Nimble-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Nimble : NSObject 3 | @end 4 | @implementation PodsDummy_Nimble 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Nimble/Nimble-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Nimble/Nimble-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "Nimble.h" 14 | #import "DSL.h" 15 | #import "NMBExceptionCapture.h" 16 | #import "NMBStringify.h" 17 | #import "CwlCatchException.h" 18 | #import "CwlMachBadInstructionHandler.h" 19 | #import "mach_excServer.h" 20 | 21 | FOUNDATION_EXPORT double NimbleVersionNumber; 22 | FOUNDATION_EXPORT const unsigned char NimbleVersionString[]; 23 | 24 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Nimble/Nimble.modulemap: -------------------------------------------------------------------------------- 1 | framework module Nimble { 2 | umbrella header "Nimble-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Nimble/Nimble.xcconfig: -------------------------------------------------------------------------------- 1 | APPLICATION_EXTENSION_API_ONLY = YES 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Nimble 3 | DEFINES_MODULE = YES 4 | ENABLE_BITCODE = NO 5 | ENABLE_TESTING_SEARCH_PATHS = YES 6 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" 7 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 8 | OTHER_LDFLAGS = $(inherited) -Xlinker -no_application_extension -weak-lXCTestSwiftSupport -weak_framework "XCTest" 9 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS $(inherited) -suppress-warnings 10 | PODS_BUILD_DIR = ${BUILD_DIR} 11 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 12 | PODS_ROOT = ${SRCROOT} 13 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Nimble 14 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 15 | SKIP_INSTALL = YES 16 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-App/Pods-App-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-App/Pods-App-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_App : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_App 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-App/Pods-App-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_AppVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_AppVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Authentication" "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch" "${PODS_CONFIGURATION_BUILD_DIR}/Networking" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Authentication/Authentication.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch/MoviesSearch.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Networking/Networking.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "Authentication" -framework "MoviesSearch" -framework "Networking" -weak_framework "SwiftUI" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-App/Pods-App.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_App { 2 | umbrella header "Pods-App-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Authentication" "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch" "${PODS_CONFIGURATION_BUILD_DIR}/Networking" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Authentication/Authentication.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch/MoviesSearch.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Networking/Networking.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "Authentication" -framework "MoviesSearch" -framework "Networking" -weak_framework "SwiftUI" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-AppUITests/Pods-AppUITests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-AppUITests/Pods-AppUITests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_AppUITests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_AppUITests 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-AppUITests/Pods-AppUITests-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_AppUITestsVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_AppUITestsVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-AppUITests/Pods-AppUITests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Authentication" "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch" "${PODS_CONFIGURATION_BUILD_DIR}/Networking" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Authentication/Authentication.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch/MoviesSearch.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Networking/Networking.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "Authentication" -framework "MoviesSearch" -framework "Networking" -weak_framework "SwiftUI" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-AppUITests/Pods-AppUITests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_AppUITests { 2 | umbrella header "Pods-AppUITests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-AppUITests/Pods-AppUITests.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Authentication" "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch" "${PODS_CONFIGURATION_BUILD_DIR}/Networking" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Authentication/Authentication.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch/MoviesSearch.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Networking/Networking.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "Authentication" -framework "MoviesSearch" -framework "Networking" -weak_framework "SwiftUI" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Authentication_Example/Pods-Authentication_Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Authentication_Example/Pods-Authentication_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Authentication_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Authentication_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Authentication_Example/Pods-Authentication_Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_Authentication_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_Authentication_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Authentication_Example/Pods-Authentication_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Authentication" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Authentication/Authentication.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "Authentication" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/../../.. 11 | PODS_ROOT = ${SRCROOT}/../../../Pods 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Authentication_Example/Pods-Authentication_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Authentication_Example { 2 | umbrella header "Pods-Authentication_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Authentication_Example/Pods-Authentication_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/Authentication" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Authentication/Authentication.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "Authentication" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/../../.. 11 | PODS_ROOT = ${SRCROOT}/../../../Pods 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MoviesSearch_Example/Pods-MoviesSearch_Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MoviesSearch_Example/Pods-MoviesSearch_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_MoviesSearch_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_MoviesSearch_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MoviesSearch_Example/Pods-MoviesSearch_Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_MoviesSearch_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_MoviesSearch_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MoviesSearch_Example/Pods-MoviesSearch_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch" "${PODS_CONFIGURATION_BUILD_DIR}/Networking" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch/MoviesSearch.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Networking/Networking.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "MoviesSearch" -framework "Networking" -weak_framework "SwiftUI" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/../../.. 11 | PODS_ROOT = ${SRCROOT}/../../../Pods 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MoviesSearch_Example/Pods-MoviesSearch_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_MoviesSearch_Example { 2 | umbrella header "Pods-MoviesSearch_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MoviesSearch_Example/Pods-MoviesSearch_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch" "${PODS_CONFIGURATION_BUILD_DIR}/Networking" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MoviesSearch/MoviesSearch.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Networking/Networking.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "MoviesSearch" -framework "Networking" -weak_framework "SwiftUI" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/../../.. 11 | PODS_ROOT = ${SRCROOT}/../../../Pods 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Networking_Example/Pods-Networking_Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Networking_Example/Pods-Networking_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Networking 5 | 6 | Copyright (c) 2019 olehkudinovolx 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Networking_Example/Pods-Networking_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Networking_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Networking_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Networking_Example/Pods-Networking_Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_Networking_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_Networking_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Networking_Example/Pods-Networking_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Networking" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Networking/Networking.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Networking" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/../../.. 11 | PODS_ROOT = ${SRCROOT}/../../../Pods 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Networking_Example/Pods-Networking_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Networking_Example { 2 | umbrella header "Pods-Networking_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Networking_Example/Pods-Networking_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Networking" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Networking/Networking.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Networking" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/../../.. 11 | PODS_ROOT = ${SRCROOT}/../../../Pods 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Quick/Quick-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 4.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Quick/Quick-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Quick : NSObject 3 | @end 4 | @implementation PodsDummy_Quick 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Quick/Quick-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Quick/Quick-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "QuickConfiguration.h" 14 | #import "QCKDSL.h" 15 | #import "Quick.h" 16 | #import "QuickSpec.h" 17 | 18 | FOUNDATION_EXPORT double QuickVersionNumber; 19 | FOUNDATION_EXPORT const unsigned char QuickVersionString[]; 20 | 21 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Quick/Quick.modulemap: -------------------------------------------------------------------------------- 1 | framework module Quick { 2 | umbrella header "Quick-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Quick/Quick.xcconfig: -------------------------------------------------------------------------------- 1 | APPLICATION_EXTENSION_API_ONLY = YES 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Quick 3 | DEFINES_MODULE = YES 4 | ENABLE_BITCODE = NO 5 | ENABLE_TESTING_SEARCH_PATHS = YES 6 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" 7 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 8 | OTHER_LDFLAGS = $(inherited) -Xlinker -no_application_extension -framework "XCTest" 9 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 10 | PODS_BUILD_DIR = ${BUILD_DIR} 11 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 12 | PODS_ROOT = ${SRCROOT} 13 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Quick 14 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 15 | SKIP_INSTALL = YES 16 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/iOSSnapshotTestCase/iOSSnapshotTestCase-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 8.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/iOSSnapshotTestCase/iOSSnapshotTestCase-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_iOSSnapshotTestCase : NSObject 3 | @end 4 | @implementation PodsDummy_iOSSnapshotTestCase 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/iOSSnapshotTestCase/iOSSnapshotTestCase-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/iOSSnapshotTestCase/iOSSnapshotTestCase-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "FBSnapshotTestCase.h" 14 | #import "FBSnapshotTestCasePlatform.h" 15 | #import "FBSnapshotTestController.h" 16 | 17 | FOUNDATION_EXPORT double FBSnapshotTestCaseVersionNumber; 18 | FOUNDATION_EXPORT const unsigned char FBSnapshotTestCaseVersionString[]; 19 | 20 | -------------------------------------------------------------------------------- /Pods/Target Support Files/iOSSnapshotTestCase/iOSSnapshotTestCase.modulemap: -------------------------------------------------------------------------------- 1 | framework module FBSnapshotTestCase { 2 | umbrella header "iOSSnapshotTestCase-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/iOSSnapshotTestCase/iOSSnapshotTestCase.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/iOSSnapshotTestCase 2 | ENABLE_BITCODE = NO 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "QuartzCore" -framework "UIKit" -framework "XCTest" 6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 7 | PODS_BUILD_DIR = ${BUILD_DIR} 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT} 10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/iOSSnapshotTestCase 11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 12 | SKIP_INSTALL = YES 13 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 14 | -------------------------------------------------------------------------------- /Pods/iOSSnapshotTestCase/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2018, Uber Technologies, Inc. 4 | Copyright (c) 2013-2018, Facebook, Inc. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /Pods/iOSSnapshotTestCase/src/iOSSnapshotTestCaseCore/Categories/UIApplication+KeyWindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2018, Uber Technologies, Inc. 3 | * Copyright (c) 2015-2018, Facebook, Inc. 4 | * 5 | * This source code is licensed under the MIT license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | * 8 | */ 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIApplication (KeyWindow) 15 | 16 | - (nullable UIWindow *)ub_keyWindow; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /Pods/iOSSnapshotTestCase/src/iOSSnapshotTestCaseCore/Categories/UIApplication+KeyWindow.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2018, Uber Technologies, Inc. 3 | * Copyright (c) 2015-2018, Facebook, Inc. 4 | * 5 | * This source code is licensed under the MIT license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | * 8 | */ 9 | 10 | #if SWIFT_PACKAGE 11 | #import "UIApplication+KeyWindow.h" 12 | #else 13 | #import 14 | #endif 15 | 16 | @implementation UIApplication (KeyWindow) 17 | 18 | - (nullable UIWindow *)ub_keyWindow 19 | { 20 | #pragma GCC diagnostic push 21 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 22 | return UIApplication.sharedApplication.keyWindow; 23 | #pragma GCC diagnostic pop 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Pods/iOSSnapshotTestCase/src/iOSSnapshotTestCaseCore/Categories/UIImage+Diff.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Gabriel Handford on 3/1/09. 3 | // Copyright 2009-2013. All rights reserved. 4 | // Created by John Boiles on 10/20/11. 5 | // Copyright (c) 2011. All rights reserved 6 | // Modified by Felix Schulze on 2/11/13. 7 | // Copyright 2013. All rights reserved. 8 | // 9 | // Permission is hereby granted, free of charge, to any person 10 | // obtaining a copy of this software and associated documentation 11 | // files (the "Software"), to deal in the Software without 12 | // restriction, including without limitation the rights to use, 13 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following 16 | // conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | // OTHER DEALINGS IN THE SOFTWARE. 29 | // 30 | 31 | #import 32 | 33 | NS_ASSUME_NONNULL_BEGIN 34 | 35 | @interface UIImage (Diff) 36 | 37 | - (UIImage *)fb_diffWithImage:(UIImage *)image; 38 | 39 | @end 40 | 41 | NS_ASSUME_NONNULL_END 42 | -------------------------------------------------------------------------------- /Pods/iOSSnapshotTestCase/src/iOSSnapshotTestCaseCore/Categories/UIImage+Snapshot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2018, Uber Technologies, Inc. 3 | * Copyright (c) 2015-2018, Facebook, Inc. 4 | * 5 | * This source code is licensed under the MIT license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | * 8 | */ 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIImage (Snapshot) 15 | 16 | /// Uses renderInContext: to get a snapshot of the layer. 17 | + (nullable UIImage *)fb_imageForLayer:(CALayer *)layer; 18 | 19 | /// Uses renderInContext: to get a snapshot of the view layer. 20 | + (nullable UIImage *)fb_imageForViewLayer:(UIView *)view; 21 | 22 | /// Uses drawViewHierarchyInRect: to get a snapshot of the view and adds the view into a window if needed. 23 | + (nullable UIImage *)fb_imageForView:(UIView *)view; 24 | 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /README_FILES/ModulesDependencies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/README_FILES/ModulesDependencies.png -------------------------------------------------------------------------------- /README_FILES/ModulesDependenciesAuth.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/README_FILES/ModulesDependenciesAuth.jpg -------------------------------------------------------------------------------- /README_FILES/ModulesScaled.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/README_FILES/ModulesScaled.jpeg -------------------------------------------------------------------------------- /README_FILES/VideoPart1Preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/README_FILES/VideoPart1Preview.png -------------------------------------------------------------------------------- /README_FILES/VideoPart2Preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/README_FILES/VideoPart2Preview.png -------------------------------------------------------------------------------- /SnapshotTests/FailureDiffs/MoviesSearch_Unit_Tests.MoviesListViewTests/diff_test_whenHasItems_thenShowItemsOnScreen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/SnapshotTests/FailureDiffs/MoviesSearch_Unit_Tests.MoviesListViewTests/diff_test_whenHasItems_thenShowItemsOnScreen@3x.png -------------------------------------------------------------------------------- /SnapshotTests/FailureDiffs/MoviesSearch_Unit_Tests.MoviesListViewTests/diff_test_whenViewIsEmpty_thenShowEmptyScreen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/SnapshotTests/FailureDiffs/MoviesSearch_Unit_Tests.MoviesListViewTests/diff_test_whenViewIsEmpty_thenShowEmptyScreen@3x.png -------------------------------------------------------------------------------- /SnapshotTests/FailureDiffs/MoviesSearch_Unit_Tests.MoviesListViewTests/failed_test_whenHasItems_thenShowItemsOnScreen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/SnapshotTests/FailureDiffs/MoviesSearch_Unit_Tests.MoviesListViewTests/failed_test_whenHasItems_thenShowItemsOnScreen@3x.png -------------------------------------------------------------------------------- /SnapshotTests/FailureDiffs/MoviesSearch_Unit_Tests.MoviesListViewTests/failed_test_whenViewIsEmpty_thenShowEmptyScreen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/SnapshotTests/FailureDiffs/MoviesSearch_Unit_Tests.MoviesListViewTests/failed_test_whenViewIsEmpty_thenShowEmptyScreen@3x.png -------------------------------------------------------------------------------- /SnapshotTests/FailureDiffs/MoviesSearch_Unit_Tests.MoviesListViewTests/reference_test_whenHasItems_thenShowItemsOnScreen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/SnapshotTests/FailureDiffs/MoviesSearch_Unit_Tests.MoviesListViewTests/reference_test_whenHasItems_thenShowItemsOnScreen@3x.png -------------------------------------------------------------------------------- /SnapshotTests/FailureDiffs/MoviesSearch_Unit_Tests.MoviesListViewTests/reference_test_whenViewIsEmpty_thenShowEmptyScreen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/SnapshotTests/FailureDiffs/MoviesSearch_Unit_Tests.MoviesListViewTests/reference_test_whenViewIsEmpty_thenShowEmptyScreen@3x.png -------------------------------------------------------------------------------- /SnapshotTests/ReferenceImages_64/MoviesSearch_Unit_Tests.MoviesListViewTests/test_whenHasItems_thenShowItemsOnScreen@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/SnapshotTests/ReferenceImages_64/MoviesSearch_Unit_Tests.MoviesListViewTests/test_whenHasItems_thenShowItemsOnScreen@2x.png -------------------------------------------------------------------------------- /SnapshotTests/ReferenceImages_64/MoviesSearch_Unit_Tests.MoviesListViewTests/test_whenHasItems_thenShowItemsOnScreen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/SnapshotTests/ReferenceImages_64/MoviesSearch_Unit_Tests.MoviesListViewTests/test_whenHasItems_thenShowItemsOnScreen@3x.png -------------------------------------------------------------------------------- /SnapshotTests/ReferenceImages_64/MoviesSearch_Unit_Tests.MoviesListViewTests/test_whenViewIsEmpty_thenShowEmptyScreen@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/SnapshotTests/ReferenceImages_64/MoviesSearch_Unit_Tests.MoviesListViewTests/test_whenViewIsEmpty_thenShowEmptyScreen@2x.png -------------------------------------------------------------------------------- /SnapshotTests/ReferenceImages_64/MoviesSearch_Unit_Tests.MoviesListViewTests/test_whenViewIsEmpty_thenShowEmptyScreen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kudoleh/iOS-Modular-Architecture/68921e1a254783f8800c1a678e7d218d6c65ceec/SnapshotTests/ReferenceImages_64/MoviesSearch_Unit_Tests.MoviesListViewTests/test_whenViewIsEmpty_thenShowEmptyScreen@3x.png -------------------------------------------------------------------------------- /fastlane/Appfile: -------------------------------------------------------------------------------- 1 | # app_identifier("[[APP_IDENTIFIER]]") # The bundle identifier of your app 2 | # apple_id("[[APPLE_ID]]") # Your Apple email address 3 | 4 | 5 | # For more information about the Appfile, see: 6 | # https://docs.fastlane.tools/advanced/#appfile 7 | -------------------------------------------------------------------------------- /fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | # This file contains the fastlane.tools configuration 2 | 3 | default_platform(:ios) 4 | 5 | simulator = "iPhone 8 Plus" 6 | 7 | all_modules_schemes = [ 8 | 'MoviesSearch-Example', 9 | 'Networking-Example', 10 | 'Authentication-Example', 11 | ] 12 | 13 | 14 | #### TESTS #### 15 | 16 | desc "Runs all unit and UI tests and tests if all modules are buildable" 17 | desc "Use `fastlane test`" 18 | lane :test do |options| 19 | 20 | # Check if all modules are buildable 21 | all_modules_schemes.each do |s| 22 | UI.message "Testing if module #{s} is buildable" 23 | scan( 24 | scheme: s, 25 | device: simulator, 26 | build_for_testing: true, 27 | ) 28 | end 29 | 30 | # Run all unit and UI tests, and test if App is buildable 31 | scan( 32 | scheme: "App", 33 | device: simulator, 34 | ) 35 | 36 | end 37 | 38 | -------------------------------------------------------------------------------- /fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ================ 3 | # Installation 4 | 5 | Make sure you have the latest version of the Xcode command line tools installed: 6 | 7 | ``` 8 | xcode-select --install 9 | ``` 10 | 11 | Install _fastlane_ using 12 | ``` 13 | [sudo] gem install fastlane -NV 14 | ``` 15 | or alternatively using `brew cask install fastlane` 16 | 17 | # Available Actions 18 | ### test 19 | ``` 20 | fastlane test 21 | ``` 22 | Runs all unit and UI tests and tests if all modules are buildable 23 | 24 | Use `fastlane test` 25 | 26 | ---- 27 | 28 | This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. 29 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). 30 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 31 | -------------------------------------------------------------------------------- /fastlane/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | --------------------------------------------------------------------------------