├── .gitattributes ├── .gitignore ├── .sourcery.yml ├── Mocks ├── AutoMockable.generated.swift ├── AutoMockable.stencil ├── NetworkServiceTypeMock.swift └── URLProtocolMock.swift ├── README.md ├── TMDB.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── TMDB.xcscheme ├── TMDB ├── Info.plist ├── Resources │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── error.imageset │ │ │ ├── Contents.json │ │ │ └── iconfinder_ic_error_outline_48px_3669347.pdf │ │ ├── search.imageset │ │ │ ├── Contents.json │ │ │ └── iconfinder_search_322497.pdf │ │ └── star.imageset │ │ │ ├── Contents.json │ │ │ └── star.pdf │ └── Base.lproj │ │ └── LaunchScreen.storyboard └── Sources │ ├── AppDelegate.swift │ ├── FlowCoordinators │ ├── ApplicationComponentsFactory.swift │ ├── ApplicationFlowCoordinator.swift │ ├── FlowCoordinator.swift │ ├── FlowCoordinatorDependencyProviders.swift │ └── MoviesSearchFlowCoordinator.swift │ ├── Screens │ ├── Alert │ │ ├── AlertViewController.swift │ │ ├── AlertViewController.xib │ │ └── AlertViewModel.swift │ ├── Details │ │ ├── MovieDetailsViewController.swift │ │ ├── MovieDetailsViewController.xib │ │ ├── MovieDetailsViewModel.swift │ │ └── MovieDetailsViewModelType.swift │ ├── Search │ │ ├── MovieTableViewCell.swift │ │ ├── MovieTableViewCell.xib │ │ ├── MovieViewModel.swift │ │ ├── MovieViewModelBuilder.swift │ │ ├── MoviesSearchNavigator.swift │ │ ├── MoviesSearchViewController.swift │ │ ├── MoviesSearchViewController.xib │ │ ├── MoviesSearchViewModel.swift │ │ └── MoviesSearchViewModelType.swift │ └── Utils │ │ ├── UITableView+Common.swift │ │ └── UIViewController+Child.swift │ ├── Services │ ├── ImageLoader │ │ ├── ImageCache.swift │ │ ├── ImageLoaderService.swift │ │ └── ImageLoaderServiceType.swift │ ├── Network │ │ ├── NetworkService.swift │ │ ├── NetworkServiceType.swift │ │ └── Resource.swift │ ├── Scheduler.swift │ └── ServicesProvider.swift │ ├── UseCases │ ├── ApiConstants.swift │ ├── Entities │ │ ├── Genre.swift │ │ ├── ImageSize.swift │ │ ├── Movie.swift │ │ └── Movies.swift │ ├── MoviesUseCase.swift │ └── Resource+Movie.swift │ ├── Utils │ ├── AccessibilityIdentifiers.swift │ ├── AutoMockable.swift │ └── Publisher+Utils.swift │ └── main.swift ├── TMDBTests ├── Frameworks │ └── EarlGrey.framework │ │ ├── EarlGrey │ │ ├── Headers │ │ ├── EarlGrey.h │ │ ├── EarlGreyImpl.h │ │ ├── GREYAction.h │ │ ├── GREYActionBlock.h │ │ ├── GREYActions.h │ │ ├── GREYAllOf.h │ │ ├── GREYAnyOf.h │ │ ├── GREYAssertion.h │ │ ├── GREYAssertionBlock.h │ │ ├── GREYAssertionDefines.h │ │ ├── GREYAssertions.h │ │ ├── GREYBaseAction.h │ │ ├── GREYBaseMatcher.h │ │ ├── GREYCondition.h │ │ ├── GREYConfiguration.h │ │ ├── GREYConstants.h │ │ ├── GREYDataEnumerator.h │ │ ├── GREYDefines.h │ │ ├── GREYDescription.h │ │ ├── GREYDispatchQueueIdlingResource.h │ │ ├── GREYElementFinder.h │ │ ├── GREYElementHierarchy.h │ │ ├── GREYElementInteraction.h │ │ ├── GREYElementMatcherBlock.h │ │ ├── GREYFailureHandler.h │ │ ├── GREYFrameworkException.h │ │ ├── GREYIdlingResource.h │ │ ├── GREYInteraction.h │ │ ├── GREYLayoutConstraint.h │ │ ├── GREYManagedObjectContextIdlingResource.h │ │ ├── GREYMatcher.h │ │ ├── GREYMatchers.h │ │ ├── GREYNSTimerIdlingResource.h │ │ ├── GREYNot.h │ │ ├── GREYOperationQueueIdlingResource.h │ │ ├── GREYProvider.h │ │ ├── GREYScreenshotUtil.h │ │ ├── GREYScrollActionError.h │ │ ├── GREYSyncAPI.h │ │ ├── GREYTestHelper.h │ │ └── GREYUIThreadExecutor.h │ │ ├── Info.plist │ │ ├── Modules │ │ └── module.modulemap │ │ ├── PrivateHeaders │ │ ├── CAAnimation+GREYAdditions.h │ │ ├── CALayer+GREYAdditions.h │ │ ├── CGGeometry+GREYAdditions.h │ │ ├── GREYActions+Internal.h │ │ ├── GREYAnalytics.h │ │ ├── GREYAnalyticsDelegate.h │ │ ├── GREYAppStateTracker.h │ │ ├── GREYAppStateTrackerObject.h │ │ ├── GREYAppleInternals.h │ │ ├── GREYAssertions+Internal.h │ │ ├── GREYCAAnimationDelegate.h │ │ ├── GREYChangeStepperAction.h │ │ ├── GREYDispatchQueueTracker.h │ │ ├── GREYElementInteraction+Internal.h │ │ ├── GREYElementProvider.h │ │ ├── GREYError+Internal.h │ │ ├── GREYError.h │ │ ├── GREYErrorConstants.h │ │ ├── GREYFailureFormatter.h │ │ ├── GREYFailureScreenshotter.h │ │ ├── GREYInteractionDataSource.h │ │ ├── GREYKeyboard.h │ │ ├── GREYLogger.h │ │ ├── GREYMultiFingerSwipeAction.h │ │ ├── GREYNSURLConnectionDelegate.h │ │ ├── GREYObjcRuntime.h │ │ ├── GREYObjectDeallocationTracker.h │ │ ├── GREYObjectFormatter.h │ │ ├── GREYPathGestureUtils.h │ │ ├── GREYPickerAction.h │ │ ├── GREYPinchAction.h │ │ ├── GREYRunLoopSpinner.h │ │ ├── GREYScreenshotUtil+Internal.h │ │ ├── GREYScrollAction.h │ │ ├── GREYScrollToContentEdgeAction.h │ │ ├── GREYSlideAction.h │ │ ├── GREYStopwatch.h │ │ ├── GREYStringDescription.h │ │ ├── GREYSurrogateDelegate.h │ │ ├── GREYSwipeAction.h │ │ ├── GREYSwizzler.h │ │ ├── GREYSyntheticEvents.h │ │ ├── GREYTapAction.h │ │ ├── GREYTestCaseInvocation.h │ │ ├── GREYTimedIdlingResource.h │ │ ├── GREYTouchInfo.h │ │ ├── GREYTouchInjector.h │ │ ├── GREYTraversal.h │ │ ├── GREYTraversalBFS.h │ │ ├── GREYTraversalDFS.h │ │ ├── GREYUIThreadExecutor+Internal.h │ │ ├── GREYUIWebViewDelegate.h │ │ ├── GREYUIWindowProvider.h │ │ ├── GREYVisibilityChecker.h │ │ ├── GREYZeroToleranceTimer.h │ │ ├── NSError+GREYAdditions.h │ │ ├── NSObject+GREYAdditions.h │ │ ├── NSRunLoop+GREYAdditions.h │ │ ├── NSString+GREYAdditions.h │ │ ├── NSTimer+GREYAdditions.h │ │ ├── NSURL+GREYAdditions.h │ │ ├── NSURLConnection+GREYAdditions.h │ │ ├── NSURLSession+GREYAdditions.h │ │ ├── UIAnimation+GREYAdditions.h │ │ ├── UIApplication+GREYAdditions.h │ │ ├── UIGestureRecognizer+GREYAdditions.h │ │ ├── UIScrollView+GREYAdditions.h │ │ ├── UISwitch+GREYAdditions.h │ │ ├── UITouch+GREYAdditions.h │ │ ├── UIView+GREYAdditions.h │ │ ├── UIViewController+GREYAdditions.h │ │ ├── UIWebView+GREYAdditions.h │ │ ├── UIWindow+GREYAdditions.h │ │ ├── XCTestCase+GREYAdditions.h │ │ ├── _UIModalItemsPresentingViewController_GREYAdditions.h │ │ └── __NSCFLocalDataTask_GREYAdditions.h │ │ └── _CodeSignature │ │ └── CodeResources ├── Info.plist ├── Mocks │ ├── AutoMockable.generated.swift │ ├── AutoMockable.stencil │ └── URLProtocolMock.swift ├── Responses │ ├── MovieDetails.json │ ├── Movies.json │ └── joker.jpg ├── UITests │ ├── MovieDetailsTests.swift │ ├── MoviesSearchTests.swift │ ├── Pages │ │ ├── AlertPage.swift │ │ ├── MovieDetailsPage.swift │ │ ├── MoviesSearchPage.swift │ │ └── Page.swift │ └── Utils │ │ ├── EarlGrey.swift │ │ ├── FakeAppDelegate.swift │ │ └── TMDBTestCase.swift └── UnitTests │ ├── ApplicationFlowCoordinatorTests.swift │ ├── MoviesSearchViewModelTests.swift │ ├── MoviesUseCaseTests.swift │ └── NetworkServiceTests.swift └── screenshots └── demo.gif /.gitattributes: -------------------------------------------------------------------------------- 1 | TMDBTests/Frameworks/* linguist-vendored=true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots/**/*.png 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /.sourcery.yml: -------------------------------------------------------------------------------- 1 | sources: 2 | - TMDB/Sources 3 | templates: 4 | - TMDBTests/Mocks 5 | output: 6 | TMDBTests/Mocks -------------------------------------------------------------------------------- /Mocks/NetworkServiceTypeMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TMDB 3 | // 4 | // Created by Maksym Shcheglov. 5 | // Copyright © 2021 Maksym Shcheglov. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | import Combine 10 | @testable import TMDB 11 | 12 | class NetworkServiceTypeMock: NetworkServiceType { 13 | 14 | var responses = [String:Any]() 15 | 16 | func load(_ resource: Resource) -> AnyPublisher where T : Decodable { 17 | if let response = responses[resource.url.path] as? T { 18 | return .just(response) 19 | } else if let error = responses[resource.url.path] as? NetworkError { 20 | return .fail(error) 21 | } else { 22 | return .fail(NetworkError.invalidRequest) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Mocks/URLProtocolMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TMDB 3 | // 4 | // Created by Maksym Shcheglov. 5 | // Copyright © 2021 Maksym Shcheglov. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | class URLProtocolMock: URLProtocol { 11 | static var requestHandler: ((URLRequest) throws -> (HTTPURLResponse, Data?))? 12 | 13 | override class func canInit(with request: URLRequest) -> Bool { 14 | return true 15 | } 16 | 17 | override class func canonicalRequest(for request: URLRequest) -> URLRequest { 18 | return request 19 | } 20 | 21 | override func startLoading() { 22 | guard let handler = URLProtocolMock.requestHandler else { 23 | assertionFailure("The handler is not provided!") 24 | return 25 | } 26 | 27 | do { 28 | let (response, data) = try handler(request) 29 | client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) 30 | if let data = data { 31 | client?.urlProtocol(self, didLoad: data) 32 | } 33 | client?.urlProtocolDidFinishLoading(self) 34 | } catch { 35 | client?.urlProtocol(self, didFailWithError: error) 36 | } 37 | } 38 | 39 | override func stopLoading() { 40 | // nop 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #

TMDb iOS Application

2 | 3 | This is the demo project of the article written in [my blog](https://onswiftwings.com/posts/mvvm-with-combine/). The application works as a mobile client for [The Movie DB](https://www.themoviedb.org). It follows MVVM software design pattern and is built with [Combine framework](https://developer.apple.com/documentation/combine/). 4 | 5 |

6 | 7 |

8 | -------------------------------------------------------------------------------- /TMDB.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TMDB.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TMDB/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | 33 | UISupportedInterfaceOrientations~ipad 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationPortraitUpsideDown 37 | UIInterfaceOrientationLandscapeLeft 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /TMDB/Resources/Assets.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" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /TMDB/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TMDB/Resources/Assets.xcassets/error.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "iconfinder_ic_error_outline_48px_3669347.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true, 14 | "template-rendering-intent" : "template" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TMDB/Resources/Assets.xcassets/error.imageset/iconfinder_ic_error_outline_48px_3669347.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgl0v/TMDB/5fc1aec6e6552f03d90809d0b672d490b8b7759a/TMDB/Resources/Assets.xcassets/error.imageset/iconfinder_ic_error_outline_48px_3669347.pdf -------------------------------------------------------------------------------- /TMDB/Resources/Assets.xcassets/search.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "iconfinder_search_322497.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true, 14 | "template-rendering-intent" : "template" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TMDB/Resources/Assets.xcassets/search.imageset/iconfinder_search_322497.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgl0v/TMDB/5fc1aec6e6552f03d90809d0b672d490b8b7759a/TMDB/Resources/Assets.xcassets/search.imageset/iconfinder_search_322497.pdf -------------------------------------------------------------------------------- /TMDB/Resources/Assets.xcassets/star.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "star.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } -------------------------------------------------------------------------------- /TMDB/Resources/Assets.xcassets/star.imageset/star.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgl0v/TMDB/5fc1aec6e6552f03d90809d0b672d490b8b7759a/TMDB/Resources/Assets.xcassets/star.imageset/star.pdf -------------------------------------------------------------------------------- /TMDB/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 | -------------------------------------------------------------------------------- /TMDB/Sources/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 02/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | var appCoordinator: ApplicationFlowCoordinator! 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | let window = UIWindow(frame: UIScreen.main.bounds) 18 | self.appCoordinator = ApplicationFlowCoordinator(window: window, dependencyProvider: ApplicationComponentsFactory()) 19 | self.appCoordinator.start() 20 | 21 | self.window = window 22 | self.window?.makeKeyAndVisible() 23 | 24 | return true 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /TMDB/Sources/FlowCoordinators/ApplicationComponentsFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ApplicationComponentsFactory.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 02/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// The ApplicationComponentsFactory takes responsibity of creating application components and establishing dependencies between them. 12 | final class ApplicationComponentsFactory { 13 | fileprivate lazy var useCase: MoviesUseCaseType = MoviesUseCase(networkService: servicesProvider.network, imageLoaderService: servicesProvider.imageLoader) 14 | 15 | private let servicesProvider: ServicesProvider 16 | 17 | init(servicesProvider: ServicesProvider = ServicesProvider.defaultProvider()) { 18 | self.servicesProvider = servicesProvider 19 | } 20 | } 21 | 22 | extension ApplicationComponentsFactory: ApplicationFlowCoordinatorDependencyProvider { 23 | 24 | func moviesSearchNavigationController(navigator: MoviesSearchNavigator) -> UINavigationController { 25 | let viewModel = MoviesSearchViewModel(useCase: useCase, navigator: navigator) 26 | let moviesSearchViewController = MoviesSearchViewController(viewModel: viewModel) 27 | let moviesSearchNavigationController = UINavigationController(rootViewController: moviesSearchViewController) 28 | moviesSearchNavigationController.navigationBar.tintColor = .label 29 | return moviesSearchNavigationController 30 | } 31 | 32 | func movieDetailsController(_ movieId: Int) -> UIViewController { 33 | let viewModel = MovieDetailsViewModel(movieId: movieId, useCase: useCase) 34 | return MovieDetailsViewController(viewModel: viewModel) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /TMDB/Sources/FlowCoordinators/ApplicationFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ApplicationFlowCoordinator.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 02/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// The application flow coordinator. Takes responsibility about coordinating view controllers and driving the flow 12 | class ApplicationFlowCoordinator: FlowCoordinator { 13 | 14 | typealias DependencyProvider = ApplicationFlowCoordinatorDependencyProvider 15 | 16 | private let window: UIWindow 17 | private let dependencyProvider: DependencyProvider 18 | private var childCoordinators = [FlowCoordinator]() 19 | 20 | init(window: UIWindow, dependencyProvider: DependencyProvider) { 21 | self.window = window 22 | self.dependencyProvider = dependencyProvider 23 | } 24 | 25 | /// Creates all necessary dependencies and starts the flow 26 | func start() { 27 | let searchFlowCoordinator = MoviesSearchFlowCoordinator(window: window, dependencyProvider: self.dependencyProvider) 28 | childCoordinators = [searchFlowCoordinator] 29 | searchFlowCoordinator.start() 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /TMDB/Sources/FlowCoordinators/FlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FlowCoordinator.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 02/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// A `FlowCoordinator` takes responsibility about coordinating view controllers and driving the flow in the application. 12 | protocol FlowCoordinator: AnyObject { 13 | 14 | /// Stars the flow 15 | func start() 16 | } 17 | 18 | -------------------------------------------------------------------------------- /TMDB/Sources/FlowCoordinators/FlowCoordinatorDependencyProviders.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FlowCoordinatorDependencyProviders.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 02/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// The `ApplicationFlowCoordinatorDependencyProvider` protocol defines methods to satisfy external dependencies of the ApplicationFlowCoordinator 12 | protocol ApplicationFlowCoordinatorDependencyProvider: MoviesSearchFlowCoordinatorDependencyProvider {} 13 | 14 | protocol MoviesSearchFlowCoordinatorDependencyProvider: class { 15 | /// Creates UIViewController to search for a movie 16 | func moviesSearchNavigationController(navigator: MoviesSearchNavigator) -> UINavigationController 17 | 18 | // Creates UIViewController to show the details of the movie with specified identifier 19 | func movieDetailsController(_ movieId: Int) -> UIViewController 20 | } 21 | -------------------------------------------------------------------------------- /TMDB/Sources/FlowCoordinators/MoviesSearchFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesSearchFlowCoordinator.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 02/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// The `MoviesSearchFlowCoordinator` takes control over the flows on the movies search screen 12 | class MoviesSearchFlowCoordinator: FlowCoordinator { 13 | fileprivate let window: UIWindow 14 | fileprivate var searchNavigationController: UINavigationController? 15 | fileprivate let dependencyProvider: MoviesSearchFlowCoordinatorDependencyProvider 16 | 17 | init(window: UIWindow, dependencyProvider: MoviesSearchFlowCoordinatorDependencyProvider) { 18 | self.window = window 19 | self.dependencyProvider = dependencyProvider 20 | } 21 | 22 | func start() { 23 | let searchNavigationController = dependencyProvider.moviesSearchNavigationController(navigator: self) 24 | window.rootViewController = searchNavigationController 25 | self.searchNavigationController = searchNavigationController 26 | } 27 | } 28 | 29 | extension MoviesSearchFlowCoordinator: MoviesSearchNavigator { 30 | 31 | func showDetails(forMovie movieId: Int) { 32 | let controller = self.dependencyProvider.movieDetailsController(movieId) 33 | searchNavigationController?.pushViewController(controller, animated: true) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /TMDB/Sources/Screens/Alert/AlertViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlertView.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class AlertViewController: UIViewController { 12 | 13 | @IBOutlet private weak var imageView: UIImageView! 14 | @IBOutlet private weak var titleLabel: UILabel! 15 | @IBOutlet private weak var descriptionLabel: UILabel! 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | view.accessibilityIdentifier = AccessibilityIdentifiers.Alert.rootViewId 20 | titleLabel.accessibilityIdentifier = AccessibilityIdentifiers.Alert.titleLabelId 21 | descriptionLabel.accessibilityIdentifier = AccessibilityIdentifiers.Alert.descriptionLabelId 22 | } 23 | 24 | func showStartSearch() { 25 | render(viewModel: AlertViewModel.startSearch) 26 | } 27 | 28 | func showNoResults() { 29 | render(viewModel: AlertViewModel.noResults) 30 | } 31 | 32 | func showDataLoadingError() { 33 | render(viewModel: AlertViewModel.dataLoadingError) 34 | } 35 | 36 | fileprivate func render(viewModel: AlertViewModel) { 37 | titleLabel.text = viewModel.title 38 | descriptionLabel.text = viewModel.description 39 | imageView.image = viewModel.image 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /TMDB/Sources/Screens/Alert/AlertViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlertViewModel.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit.UIImage 11 | 12 | struct AlertViewModel { 13 | let title: String 14 | let description: String? 15 | let image: UIImage 16 | 17 | static var noResults: AlertViewModel { 18 | let title = NSLocalizedString("No movies found!", comment: "No movies found!") 19 | let description = NSLocalizedString("Try searching again...", comment: "Try searching again...") 20 | let image = UIImage(named: "search") ?? UIImage() 21 | return AlertViewModel(title: title, description: description, image: image) 22 | } 23 | 24 | static var startSearch: AlertViewModel { 25 | let title = NSLocalizedString("Search for a movie...", comment: "Search for a movie...") 26 | let image = UIImage(named: "search") ?? UIImage() 27 | return AlertViewModel(title: title, description: nil, image: image) 28 | } 29 | 30 | static var dataLoadingError: AlertViewModel { 31 | let title = NSLocalizedString("Can't load search results!", comment: "Can't load search results!") 32 | let description = NSLocalizedString("Something went wrong. Try searching again...", comment: "Something went wrong. Try searching again...") 33 | let image = UIImage(named: "error") ?? UIImage() 34 | return AlertViewModel(title: title, description: description, image: image) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /TMDB/Sources/Screens/Details/MovieDetailsViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovieDetailsViewModel.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 02/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Combine 11 | 12 | class MovieDetailsViewModel: MovieDetailsViewModelType { 13 | 14 | private let movieId: Int 15 | private let useCase: MoviesUseCaseType 16 | 17 | init(movieId: Int, useCase: MoviesUseCaseType) { 18 | self.movieId = movieId 19 | self.useCase = useCase 20 | } 21 | 22 | func transform(input: MovieDetailsViewModelInput) -> MovieDetailsViewModelOutput { 23 | let movieDetails = input.appear 24 | .flatMap({[unowned self] _ in self.useCase.movieDetails(with: self.movieId) }) 25 | .map({ result -> MovieDetailsState in 26 | switch result { 27 | case .success(let movie): return .success(self.viewModel(from: movie)) 28 | case .failure(let error): return .failure(error) 29 | } 30 | }) 31 | .eraseToAnyPublisher() 32 | let loading: MovieDetailsViewModelOutput = input.appear.map({_ in .loading }).eraseToAnyPublisher() 33 | 34 | return Publishers.Merge(loading, movieDetails).removeDuplicates().eraseToAnyPublisher() 35 | } 36 | 37 | private func viewModel(from movie: Movie) -> MovieViewModel { 38 | return MovieViewModelBuilder.viewModel(from: movie, imageLoader: {[unowned self] movie in self.useCase.loadImage(for: movie, size: .original) }) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /TMDB/Sources/Screens/Details/MovieDetailsViewModelType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovieDetailsViewModelType.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 02/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Combine 11 | 12 | // INPUT 13 | struct MovieDetailsViewModelInput { 14 | /// called when a screen becomes visible 15 | let appear: AnyPublisher 16 | } 17 | 18 | // OUTPUT 19 | enum MovieDetailsState { 20 | case loading 21 | case success(MovieViewModel) 22 | case failure(Error) 23 | } 24 | 25 | extension MovieDetailsState: Equatable { 26 | static func == (lhs: MovieDetailsState, rhs: MovieDetailsState) -> Bool { 27 | switch (lhs, rhs) { 28 | case (.loading, .loading): return true 29 | case (.success(let lhsMovie), .success(let rhsMovie)): return lhsMovie == rhsMovie 30 | case (.failure, .failure): return true 31 | default: return false 32 | } 33 | } 34 | } 35 | 36 | typealias MovieDetailsViewModelOutput = AnyPublisher 37 | 38 | protocol MovieDetailsViewModelType: AnyObject { 39 | func transform(input: MovieDetailsViewModelInput) -> MovieDetailsViewModelOutput 40 | } 41 | -------------------------------------------------------------------------------- /TMDB/Sources/Screens/Search/MovieTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovieTableViewCell.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Combine 11 | 12 | class MovieTableViewCell: UITableViewCell, NibProvidable, ReusableView { 13 | 14 | @IBOutlet private var title: UILabel! 15 | @IBOutlet private var subtitle: UILabel! 16 | @IBOutlet private var rating: UILabel! 17 | @IBOutlet private var poster: UIImageView! 18 | private var cancellable: AnyCancellable? 19 | 20 | override func prepareForReuse() { 21 | super.prepareForReuse() 22 | cancelImageLoading() 23 | } 24 | 25 | func bind(to viewModel: MovieViewModel) { 26 | cancelImageLoading() 27 | title.text = viewModel.title 28 | subtitle.text = viewModel.subtitle 29 | rating.text = viewModel.rating 30 | cancellable = viewModel.poster.sink { [unowned self] image in self.showImage(image: image) } 31 | } 32 | 33 | private func showImage(image: UIImage?) { 34 | cancelImageLoading() 35 | UIView.transition(with: self.poster, 36 | duration: 0.3, 37 | options: [.curveEaseOut, .transitionCrossDissolve], 38 | animations: { 39 | self.poster.image = image 40 | }) 41 | } 42 | 43 | private func cancelImageLoading() { 44 | poster.image = nil 45 | cancellable?.cancel() 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /TMDB/Sources/Screens/Search/MovieViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovieViewModel.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit.UIImage 11 | import Combine 12 | 13 | struct MovieViewModel { 14 | let id: Int 15 | let title: String 16 | let subtitle: String 17 | let overview: String 18 | let poster: AnyPublisher 19 | let rating: String 20 | 21 | init(id: Int, title: String, subtitle: String, overview: String, poster: AnyPublisher, rating: String) { 22 | self.id = id 23 | self.title = title 24 | self.subtitle = subtitle 25 | self.overview = overview 26 | self.poster = poster 27 | self.rating = rating 28 | } 29 | } 30 | 31 | extension MovieViewModel: Hashable { 32 | static func == (lhs: MovieViewModel, rhs: MovieViewModel) -> Bool { 33 | return lhs.id == rhs.id 34 | } 35 | 36 | func hash(into hasher: inout Hasher) { 37 | hasher.combine(id) 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /TMDB/Sources/Screens/Search/MovieViewModelBuilder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovieViewModelBuilder.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit.UIImage 11 | import Combine 12 | 13 | struct MovieViewModelBuilder { 14 | static func viewModel(from movie: Movie, imageLoader: (Movie) -> AnyPublisher) -> MovieViewModel { 15 | return MovieViewModel(id: movie.id, 16 | title: movie.title, 17 | subtitle: movie.subtitle, 18 | overview: movie.overview, 19 | poster: imageLoader(movie), 20 | rating: String(format: "%.2f", movie.voteAverage)) 21 | } 22 | } 23 | 24 | extension Movie { 25 | var genreNames: [String] { 26 | if let genreIds = genreIds { 27 | return genreIds.map { $0.description } 28 | } 29 | if let genres = genres { 30 | return genres.map { $0.name } 31 | } 32 | return [] 33 | } 34 | var subtitle: String { 35 | let genresDescription = genreNames.joined(separator: ", ") 36 | return "\(releaseYear) | \(genresDescription)" 37 | } 38 | var releaseYear: Int { 39 | let date = releaseDate.flatMap { Movie.dateFormatter.date(from: $0) } ?? Date() 40 | return Calendar.current.component(.year, from: date) 41 | } 42 | 43 | private static let dateFormatter: DateFormatter = { 44 | let formatter = DateFormatter() 45 | formatter.dateFormat = "yyyy-MM-dd" 46 | return formatter 47 | }() 48 | } 49 | -------------------------------------------------------------------------------- /TMDB/Sources/Screens/Search/MoviesSearchNavigator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesSearchNavigator.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 02/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol MoviesSearchNavigator: AutoMockable, AnyObject { 12 | /// Presents the movies details screen 13 | func showDetails(forMovie movieId: Int) 14 | } 15 | -------------------------------------------------------------------------------- /TMDB/Sources/Screens/Search/MoviesSearchViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesSearchViewModel.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 02/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Combine 11 | 12 | final class MoviesSearchViewModel: MoviesSearchViewModelType { 13 | 14 | private weak var navigator: MoviesSearchNavigator? 15 | private let useCase: MoviesUseCaseType 16 | private var cancellables: [AnyCancellable] = [] 17 | 18 | init(useCase: MoviesUseCaseType, navigator: MoviesSearchNavigator) { 19 | self.useCase = useCase 20 | self.navigator = navigator 21 | } 22 | 23 | func transform(input: MoviesSearchViewModelInput) -> MoviesSearchViewModelOuput { 24 | cancellables.forEach { $0.cancel() } 25 | cancellables.removeAll() 26 | 27 | input.selection 28 | .sink(receiveValue: { [unowned self] movieId in self.navigator?.showDetails(forMovie: movieId) }) 29 | .store(in: &cancellables) 30 | 31 | let searchInput = input.search 32 | .debounce(for: .milliseconds(300), scheduler: Scheduler.mainScheduler) 33 | .removeDuplicates() 34 | let movies = searchInput 35 | .filter({ !$0.isEmpty }) 36 | .flatMapLatest({[unowned self] query in self.useCase.searchMovies(with: query) }) 37 | .map({ result -> MoviesSearchState in 38 | switch result { 39 | case .success(let movies) where movies.items.isEmpty: return .noResults 40 | case .success(let movies): return .success(self.viewModels(from: movies.items)) 41 | case .failure(let error): return .failure(error) 42 | } 43 | }) 44 | .eraseToAnyPublisher() 45 | 46 | let initialState: MoviesSearchViewModelOuput = .just(.idle) 47 | let emptySearchString: MoviesSearchViewModelOuput = searchInput.filter({ $0.isEmpty }).map({ _ in .idle }).eraseToAnyPublisher() 48 | let idle: MoviesSearchViewModelOuput = Publishers.Merge(initialState, emptySearchString).eraseToAnyPublisher() 49 | 50 | return Publishers.Merge(idle, movies).removeDuplicates().eraseToAnyPublisher() 51 | } 52 | 53 | private func viewModels(from movies: [Movie]) -> [MovieViewModel] { 54 | return movies.map({[unowned self] movie in 55 | return MovieViewModelBuilder.viewModel(from: movie, imageLoader: {[unowned self] movie in self.useCase.loadImage(for: movie, size: .small) }) 56 | }) 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /TMDB/Sources/Screens/Search/MoviesSearchViewModelType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesSearchViewModelType.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 02/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Combine 10 | 11 | struct MoviesSearchViewModelInput { 12 | /// called when a screen becomes visible 13 | let appear: AnyPublisher 14 | // triggered when the search query is updated 15 | let search: AnyPublisher 16 | /// called when the user selected an item from the list 17 | let selection: AnyPublisher 18 | } 19 | 20 | enum MoviesSearchState { 21 | case idle 22 | case loading 23 | case success([MovieViewModel]) 24 | case noResults 25 | case failure(Error) 26 | } 27 | 28 | extension MoviesSearchState: Equatable { 29 | static func == (lhs: MoviesSearchState, rhs: MoviesSearchState) -> Bool { 30 | switch (lhs, rhs) { 31 | case (.idle, .idle): return true 32 | case (.loading, .loading): return true 33 | case (.success(let lhsMovies), .success(let rhsMovies)): return lhsMovies == rhsMovies 34 | case (.noResults, .noResults): return true 35 | case (.failure, .failure): return true 36 | default: return false 37 | } 38 | } 39 | } 40 | 41 | typealias MoviesSearchViewModelOuput = AnyPublisher 42 | 43 | protocol MoviesSearchViewModelType { 44 | func transform(input: MoviesSearchViewModelInput) -> MoviesSearchViewModelOuput 45 | } 46 | -------------------------------------------------------------------------------- /TMDB/Sources/Screens/Utils/UITableView+Common.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UITableView+Common.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol NibProvidable { 12 | static var nibName: String { get } 13 | static var nib: UINib { get } 14 | } 15 | 16 | extension NibProvidable { 17 | static var nibName: String { 18 | return "\(self)" 19 | } 20 | static var nib: UINib { 21 | return UINib(nibName: self.nibName, bundle: nil) 22 | } 23 | } 24 | 25 | protocol ReusableView { 26 | static var reuseIdentifier: String { get } 27 | } 28 | 29 | extension ReusableView { 30 | static var reuseIdentifier: String { 31 | return "\(self)" 32 | } 33 | } 34 | 35 | // Cell 36 | extension UITableView { 37 | func registerClass(cellClass `class`: T.Type) where T: ReusableView { 38 | register(`class`, forCellReuseIdentifier: `class`.reuseIdentifier) 39 | } 40 | 41 | func registerNib(cellClass `class`: T.Type) where T: NibProvidable & ReusableView { 42 | register(`class`.nib, forCellReuseIdentifier: `class`.reuseIdentifier) 43 | } 44 | 45 | func dequeueReusableCell(withClass `class`: T.Type) -> T? where T: ReusableView { 46 | return self.dequeueReusableCell(withIdentifier: `class`.reuseIdentifier) as? T 47 | } 48 | 49 | func dequeueReusableCell(withClass `class`: T.Type, forIndexPath indexPath: IndexPath) -> T where T: ReusableView { 50 | guard let cell = self.dequeueReusableCell(withIdentifier: `class`.reuseIdentifier, for: indexPath) as? T else { 51 | fatalError("Error: cell with identifier: \(`class`.reuseIdentifier) for index path: \(indexPath) is not \(T.self)") 52 | } 53 | return cell 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /TMDB/Sources/Screens/Utils/UIViewController+Child.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Child.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIViewController { 12 | public func add(_ child: UIViewController) { 13 | addChild(child) 14 | view.addSubview(child.view) 15 | child.view.translatesAutoresizingMaskIntoConstraints = false 16 | NSLayoutConstraint.activate([ 17 | child.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), 18 | child.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), 19 | child.view.topAnchor.constraint(equalTo: view.topAnchor), 20 | child.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), 21 | ]) 22 | child.didMove(toParent: self) 23 | } 24 | 25 | public func remove(_ child: UIViewController) { 26 | guard child.parent != nil else { 27 | return 28 | } 29 | 30 | child.willMove(toParent: nil) 31 | child.view.removeFromSuperview() 32 | child.removeFromParent() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /TMDB/Sources/Services/ImageLoader/ImageLoaderService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageLoader.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit.UIImage 11 | import Combine 12 | 13 | final class ImageLoaderService: ImageLoaderServiceType { 14 | 15 | private let cache: ImageCacheType = ImageCache() 16 | 17 | func loadImage(from url: URL) -> AnyPublisher { 18 | if let image = cache.image(for: url) { 19 | return .just(image) 20 | } 21 | return URLSession.shared.dataTaskPublisher(for: url) 22 | .map { (data, response) -> UIImage? in return UIImage(data: data) } 23 | .catch { error in return Just(nil) } 24 | .handleEvents(receiveOutput: {[unowned self] image in 25 | guard let image = image else { return } 26 | self.cache.insertImage(image, for: url) 27 | }) 28 | .print("Image loading \(url):") 29 | .eraseToAnyPublisher() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TMDB/Sources/Services/ImageLoader/ImageLoaderServiceType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageLoaderServiceType.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit.UIImage 11 | import Combine 12 | 13 | protocol ImageLoaderServiceType: AnyObject, AutoMockable { 14 | func loadImage(from url: URL) -> AnyPublisher 15 | } 16 | -------------------------------------------------------------------------------- /TMDB/Sources/Services/Network/NetworkService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkService.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Combine 11 | 12 | final class NetworkService: NetworkServiceType { 13 | private let session: URLSession 14 | 15 | init(session: URLSession = URLSession(configuration: URLSessionConfiguration.ephemeral)) { 16 | self.session = session 17 | } 18 | 19 | @discardableResult 20 | func load(_ resource: Resource) -> AnyPublisher { 21 | guard let request = resource.request else { 22 | return .fail(NetworkError.invalidRequest) 23 | } 24 | return session.dataTaskPublisher(for: request) 25 | .mapError { _ in NetworkError.invalidRequest } 26 | .print() 27 | .flatMap { data, response -> AnyPublisher in 28 | guard let response = response as? HTTPURLResponse else { 29 | return .fail(NetworkError.invalidResponse) 30 | } 31 | 32 | guard 200..<300 ~= response.statusCode else { 33 | return .fail(NetworkError.dataLoadingError(statusCode: response.statusCode, data: data)) 34 | } 35 | return .just(data) 36 | } 37 | .decode(type: T.self, decoder: JSONDecoder()) 38 | .eraseToAnyPublisher() 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /TMDB/Sources/Services/Network/NetworkServiceType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkServiceType.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Combine 11 | 12 | protocol NetworkServiceType: AnyObject { 13 | 14 | @discardableResult 15 | func load(_ resource: Resource) -> AnyPublisher 16 | } 17 | 18 | /// Defines the Network service errors. 19 | enum NetworkError: Error { 20 | case invalidRequest 21 | case invalidResponse 22 | case dataLoadingError(statusCode: Int, data: Data) 23 | case jsonDecodingError(error: Error) 24 | } 25 | -------------------------------------------------------------------------------- /TMDB/Sources/Services/Network/Resource.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Resource.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Resource { 12 | let url: URL 13 | let parameters: [String: CustomStringConvertible] 14 | var request: URLRequest? { 15 | guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { 16 | return nil 17 | } 18 | components.queryItems = parameters.keys.map { key in 19 | URLQueryItem(name: key, value: parameters[key]?.description) 20 | } 21 | guard let url = components.url else { 22 | return nil 23 | } 24 | return URLRequest(url: url) 25 | } 26 | 27 | init(url: URL, parameters: [String: CustomStringConvertible] = [:]) { 28 | self.url = url 29 | self.parameters = parameters 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TMDB/Sources/Services/Scheduler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Scheduler.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Combine 11 | 12 | final class Scheduler { 13 | 14 | static var backgroundWorkScheduler: OperationQueue = { 15 | let operationQueue = OperationQueue() 16 | operationQueue.maxConcurrentOperationCount = 5 17 | operationQueue.qualityOfService = QualityOfService.userInitiated 18 | return operationQueue 19 | }() 20 | 21 | static let mainScheduler = RunLoop.main 22 | 23 | } 24 | -------------------------------------------------------------------------------- /TMDB/Sources/Services/ServicesProvider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ServicesProvider.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class ServicesProvider { 12 | let network: NetworkServiceType 13 | let imageLoader: ImageLoaderServiceType 14 | 15 | static func defaultProvider() -> ServicesProvider { 16 | let network = NetworkService() 17 | let imageLoader = ImageLoaderService() 18 | return ServicesProvider(network: network, imageLoader: imageLoader) 19 | } 20 | 21 | init(network: NetworkServiceType, imageLoader: ImageLoaderServiceType) { 22 | self.network = network 23 | self.imageLoader = imageLoader 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /TMDB/Sources/UseCases/ApiConstants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TMDBApiConstants.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct ApiConstants { 12 | static let apiKey = "181af7fcab50e40fabe2d10cc8b90e37" 13 | static let baseUrl = URL(string: "https://api.themoviedb.org/3")! 14 | static let originalImageUrl = URL(string: "https://image.tmdb.org/t/p/original")! 15 | static let smallImageUrl = URL(string: "https://image.tmdb.org/t/p/w154")! 16 | } 17 | -------------------------------------------------------------------------------- /TMDB/Sources/UseCases/Entities/Genre.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Genre.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Genre: Decodable { 12 | let id: GenreId 13 | let name: String 14 | } 15 | 16 | enum GenreId: Int, CustomStringConvertible, Decodable, Hashable { 17 | case action = 28 18 | case adventure = 12 19 | case animation = 16 20 | case comedy = 35 21 | case crime = 80 22 | case documentary = 99 23 | case drama = 18 24 | case family = 10751 25 | case fantasy = 14 26 | case history = 36 27 | case horror = 27 28 | case music = 10402 29 | case mystery = 9648 30 | case romance = 10749 31 | case scienceFiction = 878 32 | case tvMovie = 10770 33 | case thriller = 53 34 | case war = 10752 35 | case western = 37 36 | 37 | var description: String { 38 | switch self { 39 | case .action: return NSLocalizedString("Action", comment: "Action") 40 | case .adventure: return NSLocalizedString("Adventure", comment: "Adventure") 41 | case .animation: return NSLocalizedString("Animation", comment: "Animation") 42 | case .comedy: return NSLocalizedString("Comedy", comment: "Comedy") 43 | case .crime: return NSLocalizedString("Crime", comment: "Crime") 44 | case .documentary: return NSLocalizedString("Documentary", comment: "Documentary") 45 | case .drama: return NSLocalizedString("Drama", comment: "Drama") 46 | case .family: return NSLocalizedString("Family", comment: "Family") 47 | case .fantasy: return NSLocalizedString("Fantasy", comment: "Fantasy") 48 | case .history: return NSLocalizedString("History", comment: "History") 49 | case .horror: return NSLocalizedString("Horror", comment: "Horror") 50 | case .music: return NSLocalizedString("Music", comment: "Music") 51 | case .mystery: return NSLocalizedString("Mystery", comment: "Mystery") 52 | case .romance: return NSLocalizedString("Romance", comment: "Romance") 53 | case .scienceFiction: return NSLocalizedString("Science Fiction", comment: "Science Fiction") 54 | case .tvMovie: return NSLocalizedString("TV Movie", comment: "TV Movie") 55 | case .thriller: return NSLocalizedString("Thriller", comment: "Thriller") 56 | case .war: return NSLocalizedString("War", comment: "War") 57 | case .western: return NSLocalizedString("Western", comment: "Western") 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /TMDB/Sources/UseCases/Entities/ImageSize.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageSize.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 06/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum ImageSize { 12 | case small 13 | case original 14 | var url: URL { 15 | switch self { 16 | case .small: return ApiConstants.smallImageUrl 17 | case .original: return ApiConstants.originalImageUrl 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TMDB/Sources/UseCases/Entities/Movie.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Entities.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Movie { 12 | let id: Int 13 | let title: String 14 | let overview: String 15 | let poster: String? 16 | let voteAverage: Float 17 | let releaseDate: String? 18 | let genreIds: [GenreId]? 19 | let genres: [Genre]? 20 | } 21 | 22 | extension Movie: Hashable { 23 | static func == (lhs: Movie, rhs: Movie) -> Bool { 24 | return lhs.id == rhs.id 25 | } 26 | 27 | func hash(into hasher: inout Hasher) { 28 | hasher.combine(id) 29 | } 30 | } 31 | 32 | extension Movie: Decodable { 33 | enum CodingKeys: String, CodingKey { 34 | case id 35 | case title 36 | case overview 37 | case poster = "poster_path" 38 | case voteAverage = "vote_average" 39 | case releaseDate = "release_date" 40 | case genreIds = "genre_ids" 41 | case genres = "genres" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /TMDB/Sources/UseCases/Entities/Movies.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Movies.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Movies { 12 | let items: [Movie] 13 | } 14 | 15 | extension Movies: Decodable { 16 | 17 | enum CodingKeys: String, CodingKey { 18 | case items = "results" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TMDB/Sources/UseCases/MoviesUseCase.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesUseCase.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Combine 11 | import UIKit.UIImage 12 | 13 | protocol MoviesUseCaseType: AutoMockable { 14 | 15 | /// Runs movies search with a query string 16 | func searchMovies(with name: String) -> AnyPublisher, Never> 17 | 18 | /// Fetches details for movie with specified id 19 | func movieDetails(with id: Int) -> AnyPublisher, Never> 20 | 21 | // Loads image for the given movie 22 | func loadImage(for movie: Movie, size: ImageSize) -> AnyPublisher 23 | } 24 | 25 | final class MoviesUseCase: MoviesUseCaseType { 26 | 27 | private let networkService: NetworkServiceType 28 | private let imageLoaderService: ImageLoaderServiceType 29 | 30 | init(networkService: NetworkServiceType, imageLoaderService: ImageLoaderServiceType) { 31 | self.networkService = networkService 32 | self.imageLoaderService = imageLoaderService 33 | } 34 | 35 | func searchMovies(with name: String) -> AnyPublisher, Never> { 36 | return networkService 37 | .load(Resource.movies(query: name)) 38 | .map { .success($0) } 39 | .catch { error -> AnyPublisher, Never> in .just(.failure(error)) } 40 | .subscribe(on: Scheduler.backgroundWorkScheduler) 41 | .receive(on: Scheduler.mainScheduler) 42 | .eraseToAnyPublisher() 43 | } 44 | 45 | func movieDetails(with id: Int) -> AnyPublisher, Never> { 46 | return networkService 47 | .load(Resource.details(movieId: id)) 48 | .map { .success($0) } 49 | .catch { error -> AnyPublisher, Never> in .just(.failure(error)) } 50 | .subscribe(on: Scheduler.backgroundWorkScheduler) 51 | .receive(on: Scheduler.mainScheduler) 52 | .eraseToAnyPublisher() 53 | } 54 | 55 | func loadImage(for movie: Movie, size: ImageSize) -> AnyPublisher { 56 | return Deferred { return Just(movie.poster) } 57 | .flatMap({[unowned self] poster -> AnyPublisher in 58 | guard let poster = movie.poster else { return .just(nil) } 59 | let url = size.url.appendingPathComponent(poster) 60 | return self.imageLoaderService.loadImage(from: url) 61 | }) 62 | .subscribe(on: Scheduler.backgroundWorkScheduler) 63 | .receive(on: Scheduler.mainScheduler) 64 | .share() 65 | .eraseToAnyPublisher() 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /TMDB/Sources/UseCases/Resource+Movie.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Resource+Movie.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Resource { 12 | 13 | static func movies(query: String) -> Resource { 14 | let url = ApiConstants.baseUrl.appendingPathComponent("/search/movie") 15 | let parameters: [String : CustomStringConvertible] = [ 16 | "api_key": ApiConstants.apiKey, 17 | "query": query, 18 | "language": Locale.preferredLanguages[0] 19 | ] 20 | return Resource(url: url, parameters: parameters) 21 | } 22 | 23 | static func details(movieId: Int) -> Resource { 24 | let url = ApiConstants.baseUrl.appendingPathComponent("/movie/\(movieId)") 25 | let parameters: [String : CustomStringConvertible] = [ 26 | "api_key": ApiConstants.apiKey, 27 | "language": Locale.preferredLanguages[0] 28 | ] 29 | return Resource(url: url, parameters: parameters) 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /TMDB/Sources/Utils/AccessibilityIdentifiers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AccessibilityIdentifiers.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 09/05/2020. 6 | // Copyright © 2020 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct AccessibilityIdentifiers { 12 | 13 | public struct MoviesSearch { 14 | public static let rootViewId = "\(MoviesSearch.self).rootViewId" 15 | public static let tableViewId = "\(MoviesSearch.self).tableViewId" 16 | public static let searchTextFieldId = "\(MoviesSearch.self).searchTextFieldId" 17 | public static let cellId = "\(MoviesSearch.self).cellId" 18 | } 19 | 20 | public struct MovieDetails { 21 | public static let rootViewId = "\(MovieDetails.self).rootViewId" 22 | public static let contentViewId = "\(MovieDetails.self).contentViewId" 23 | public static let titleLabelId = "\(MovieDetails.self).titleLabelId" 24 | public static let subtitleLabelId = "\(MovieDetails.self).subtitleLabelId" 25 | public static let descriptionLabelId = "\(MovieDetails.self).descriptionLabelId" 26 | public static let loadingIndicatorId = "\(MovieDetails.self).loadingIndicatorId" 27 | } 28 | 29 | public struct Alert { 30 | public static let rootViewId = "\(Alert.self).rootViewId" 31 | public static let titleLabelId = "\(Alert.self).titleLabelId" 32 | public static let descriptionLabelId = "\(Alert.self).descriptionLabelId" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /TMDB/Sources/Utils/AutoMockable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AutoMockable.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 08/05/2020. 6 | // Copyright © 2020 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol AutoMockable {} 12 | -------------------------------------------------------------------------------- /TMDB/Sources/Utils/Publisher+Utils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Publisher+Utils.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 05/10/2019. 6 | // Copyright © 2019 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Combine 11 | 12 | extension Publisher { 13 | 14 | // The flatMapLatest operator behaves much like the standard FlatMap operator, except that whenever 15 | // a new item is emitted by the source Publisher, it will unsubscribe to and stop mirroring the Publisher 16 | // that was generated from the previously-emitted item, and begin only mirroring the current one. 17 | func flatMapLatest(_ transform: @escaping (Self.Output) -> T) -> Publishers.SwitchToLatest> where T.Failure == Self.Failure { 18 | map(transform).switchToLatest() 19 | } 20 | } 21 | 22 | extension Publisher { 23 | 24 | static func empty() -> AnyPublisher { 25 | return Empty().eraseToAnyPublisher() 26 | } 27 | 28 | static func just(_ output: Output) -> AnyPublisher { 29 | return Just(output) 30 | .catch { _ in AnyPublisher.empty() } 31 | .eraseToAnyPublisher() 32 | } 33 | 34 | static func fail(_ error: Failure) -> AnyPublisher { 35 | return Fail(error: error).eraseToAnyPublisher() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /TMDB/Sources/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // TMDB 4 | // 5 | // Created by Maksym Shcheglov on 08/05/2020. 6 | // Copyright © 2020 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private let fakeAppDelegateClass: AnyClass? = NSClassFromString("TMDBTests.FakeAppDelegate") 12 | private let appDelegateClass: AnyClass = fakeAppDelegateClass ?? AppDelegate.self 13 | 14 | _ = UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(appDelegateClass)) 15 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/EarlGrey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgl0v/TMDB/5fc1aec6e6552f03d90809d0b672d490b8b7759a/TMDBTests/Frameworks/EarlGrey.framework/EarlGrey -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/EarlGrey.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | /** 18 | * Umbrella public header for the EarlGrey framework. 19 | * 20 | * Instead of importing individual headers, import this header using: 21 | * @code 22 | * @import EarlGrey; // if your project uses modules 23 | * @endcode 24 | * OR if your project doesn't use modules: 25 | * @code 26 | * #import 27 | * @endcode 28 | * 29 | * To learn more, check out: http://github.com/google/EarlGrey 30 | */ 31 | 32 | #import 33 | 34 | #import 35 | #import 36 | #import 37 | #import 38 | #import 39 | #import 40 | #import 41 | #import 42 | #import 43 | #import 44 | #import 45 | #import 46 | #import 47 | #import 48 | #import 49 | #import 50 | #import 51 | #import 52 | #import 53 | #import 54 | #import 55 | #import 56 | #import 57 | #import 58 | #import 59 | #import 60 | #import 61 | #import 62 | #import 63 | #import 64 | #import 65 | #import 66 | #import 67 | #import 68 | #import 69 | #import 70 | #import 71 | #import 72 | #import 73 | #import 74 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYAction.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * A protocol for actions that are performed on accessibility elements. 23 | */ 24 | @protocol GREYAction 25 | 26 | /** 27 | * Perform the action specified by the GREYAction object on an @c element if and only if the 28 | * @c element matches the constraints of the action. 29 | * 30 | * @param element The element the action is to be performed on. This must not be @c nil. 31 | * @param[out] errorOrNil Error that will be populated on failure. The implementing class should 32 | * handle the behavior when it is @c nil by, for example, logging the error 33 | * or throwing an exception. 34 | * 35 | * @return @c YES if the action succeeded, else @c NO. If an action returns @c NO, it does not 36 | * mean that the action was not performed at all but somewhere during the action execution 37 | * the error occurred and so the UI may be in an unrecoverable state. 38 | */ 39 | - (BOOL)perform:(id)element error:(__strong NSError *_Nullable *)errorOrNil; 40 | 41 | /** 42 | * A method to get the name of this action. 43 | * 44 | * @return The name of the action. If the action fails, then the name is printed along with all 45 | * other relevant information. 46 | */ 47 | - (NSString *)name; 48 | 49 | @end 50 | 51 | NS_ASSUME_NONNULL_END 52 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYAssertion.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * Protocol to which EarlGrey assertion classes must conform. 23 | */ 24 | @protocol GREYAssertion 25 | 26 | /** 27 | * Checks whether the assertion is valid for the provided @c element, throwing an exception if the 28 | * if the assertion fails and the @c errorOrNil parameter is @c nil. If a non-nil @c errorOrNil is 29 | * provided, it will be set to error that represents the assertion failure cause. 30 | * If the assertion does not accept @c nil elements, the error domain should be 31 | * @c kGREYInteractionErrorDomain and the error code @c kGREYInteractionElementNotFoundErrorCode. 32 | * GREYAssertionDefines.h defines macros for throwing common exception types. 33 | * 34 | * @param element Element on which the assertion should be checked. 35 | * @param[out] errorOrNil If non-nil, set to the cause of the assertion failure. 36 | * 37 | * @throws NSException If the assertion fails and the provided @c errorOrNil is @c nil. 38 | * The specific type depends on the implementation. 39 | * 40 | * @return @c YES if the assertion holds for the specified element, @c NO otherwise. 41 | */ 42 | - (BOOL)assert:(_Nullable id)element error:(__strong NSError *_Nullable *_Nullable)errorOrNil; 43 | 44 | /** 45 | * @return The name of the assertion. 46 | */ 47 | - (NSString *)name; 48 | 49 | @end 50 | 51 | NS_ASSUME_NONNULL_END 52 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYAssertionBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * A block that accepts an @c element, which will be invoked when an assertion is going to be 23 | * performed on the element. If the assertion fails and a non-nil @c errorOrNil is provided, 24 | * the block should populate it with the cause of failure. 25 | * 26 | * @param element Element that the assertion will be checked against. 27 | * @param[out] errorOrNil If non-nil, set to the cause of the assertion failure. 28 | * 29 | * @return @c YES if the assertion is valid for @c element, @c NO otherwise. 30 | */ 31 | typedef BOOL (^GREYCheckBlockWithError)(_Nullable id element, 32 | __strong NSError *_Nullable *_Nullable errorOrNil); 33 | 34 | /** 35 | * An interface to create GREYAssertions from blocks. 36 | */ 37 | @interface GREYAssertionBlock : NSObject 38 | 39 | /** 40 | * Creates an assertion with the given @c name and @c block that is executed when 41 | * GREYAssertion::assert:error: selector is performed on the assertion. 42 | * 43 | * @param name The assertion name. 44 | * @param block The block that will be invoked to perform the assertion. 45 | * 46 | * @return A new block-based assertion object. 47 | */ 48 | + (instancetype)assertionWithName:(NSString *)name 49 | assertionBlockWithError:(GREYCheckBlockWithError)block; 50 | 51 | /** 52 | * @remark init is not an available initializer. Use the other initializers. 53 | */ 54 | - (instancetype)init NS_UNAVAILABLE; 55 | 56 | /** 57 | * Initializes an assertion with the given @c name and @c block that is executed when 58 | * GREYAssertion::assert:error: selector is performed on the assertion. 59 | * 60 | * @param name The assertion name. 61 | * @param block The block that will be invoked to perform the assertion. 62 | * 63 | * @return The initialized assertion object. 64 | */ 65 | - (instancetype)initWithName:(NSString *)name 66 | assertionBlockWithError:(GREYCheckBlockWithError)block NS_DESIGNATED_INITIALIZER; 67 | 68 | @end 69 | 70 | NS_ASSUME_NONNULL_END 71 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYAssertions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | /** 20 | * An interface that exposes UI element assertions. 21 | */ 22 | @interface GREYAssertions : NSObject 23 | @end 24 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYBaseAction.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | @protocol GREYMatcher; 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | /** 24 | * A base class for all actions that incorporates commonalities between initialization 25 | * parameters and constraint checking. 26 | */ 27 | @interface GREYBaseAction : NSObject 28 | 29 | /** 30 | * @remark init is not an available initializer. Use the other initializers. 31 | */ 32 | - (instancetype)init NS_UNAVAILABLE; 33 | 34 | /** 35 | * The designated initializer for a base action with the provided @c constraints. 36 | * 37 | * @param name The name of the GREYAction being performed. 38 | * 39 | * @param constraints The constraints to be satisified by the element before the 40 | * action is performed. 41 | * 42 | * @return An instance of GREYBaseAction, initialized with the @c constraints for it to check for. 43 | */ 44 | - (instancetype)initWithName:(NSString *)name 45 | constraints:(id)constraints NS_DESIGNATED_INITIALIZER; 46 | 47 | /** 48 | * A method that checks that @c element satisfies @c constraints this action was initialized with. 49 | * Subclasses should call this method if they want to check for constraints in their perform:error: 50 | * implementation. 51 | * 52 | * @param element A UI element being checked for the @c constraints. 53 | * @param[out] errorOrNilPtr Error stored when an element did not satisfy the @c constraints. 54 | * If an error is set but this pointer is @c nil, 55 | * then an action failed exception is thrown. 56 | * 57 | * @throws GREYFrameworkException if constraints fail and @c errorOrNilPtr is not provided. 58 | * 59 | * @return @c YES if the constraints are satisfied on the element. @c NO otherwise. 60 | */ 61 | - (BOOL)satisfiesConstraintsForElement:(id)element error:(__strong NSError **)errorOrNilPtr; 62 | 63 | @end 64 | 65 | NS_ASSUME_NONNULL_END 66 | 67 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYBaseMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | #import 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | /** 24 | * A base class that implements the GREYMatcher protocol methods. 25 | * Prefer subclassing this class over creating your own matchers. 26 | * Every subclass must override and provide its own implementation for GREYBaseMatcher::matches: 27 | * and GREYBaseMatcher::describeTo: methods. 28 | */ 29 | @interface GREYBaseMatcher : NSObject 30 | 31 | #pragma mark - GREYMatcher 32 | 33 | /** 34 | * @see GREYMatcher::matches: 35 | * 36 | * @remark Subclasses are required to implement this method. 37 | */ 38 | - (BOOL)matches:(_Nullable id)item; 39 | 40 | /** 41 | * @see GREYMatcher::describeTo: 42 | * 43 | * @remark Subclasses are required to implement this method. 44 | */ 45 | - (void)describeTo:(id)description; 46 | 47 | @end 48 | 49 | NS_ASSUME_NONNULL_END 50 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYDataEnumerator.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * An block-based enumerator that repeatedly invokes the block to return the next object. 23 | */ 24 | @interface GREYDataEnumerator : NSEnumerator 25 | 26 | /** 27 | * @remark init is not an available initializer. Use the other initializers. 28 | */ 29 | - (instancetype)init NS_UNAVAILABLE; 30 | 31 | /** 32 | * Instantiates the enumerator with custom information and a block to return the next object. 33 | * 34 | * @param userInfo Custom object that is passed into the block. Use this for passing any 35 | * additional information required by the block. 36 | * @param nextObjectBlock A block that is invoked to return the next object in the enumerator. 37 | * 38 | * @return An instance of GREYDataEnumerator, initialized with the specified information. 39 | */ 40 | - (instancetype)initWithUserInfo:(id)userInfo 41 | block:(id(^)(id))nextObjectBlock NS_DESIGNATED_INITIALIZER; 42 | 43 | #pragma mark - NSEnumerator 44 | 45 | /** 46 | * @return The next object in the enumerator returned by the @c nextObjectBlock. 47 | */ 48 | - (id _Nullable)nextObject; 49 | /** 50 | * @return An array of all the objects in the enumerator. 51 | */ 52 | - (NSArray *)allObjects; 53 | 54 | @end 55 | 56 | NS_ASSUME_NONNULL_END 57 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | /** 18 | * @file GREYDefines.h 19 | * @brief Miscellaneous defines and macros for EarlGrey. 20 | */ 21 | 22 | #import 23 | 24 | #ifndef GREY_DEFINES_H 25 | #define GREY_DEFINES_H 26 | 27 | #define GREY_EXPORT FOUNDATION_EXPORT __used 28 | #define GREY_EXTERN FOUNDATION_EXTERN 29 | #define GREY_UNUSED_VARIABLE __attribute__((unused)) 30 | 31 | #define iOS8_0_OR_ABOVE() ([UIDevice currentDevice].systemVersion.doubleValue >= 8.0) 32 | #define iOS8_1_OR_ABOVE() ([UIDevice currentDevice].systemVersion.doubleValue >= 8.1) 33 | #define iOS8_2_OR_ABOVE() ([UIDevice currentDevice].systemVersion.doubleValue >= 8.2) 34 | #define iOS9_OR_ABOVE() ([UIDevice currentDevice].systemVersion.intValue >= 9) 35 | #define iOS10_OR_ABOVE() ([UIDevice currentDevice].systemVersion.intValue >= 10) 36 | #define iOS11_OR_ABOVE() ([UIDevice currentDevice].systemVersion.intValue >= 11) 37 | #define iOS13() ([UIDevice currentDevice].systemVersion.intValue == 13) 38 | #define iOS13_OR_ABOVE() ([UIDevice currentDevice].systemVersion.intValue >= 13) 39 | #define iOS14_OR_ABOVE() ([UIDevice currentDevice].systemVersion.intValue >= 14) 40 | 41 | #pragma mark - Math 42 | 43 | /** 44 | * @return The smallest @c int following the @c double @c x. This macro is needed to avoid 45 | * rounding errors when "modules" project setting is enabled causing math functions to 46 | * map from tgmath.h to math.h. 47 | */ 48 | #define grey_ceil(x) ((CGFloat)ceil(x)) 49 | 50 | /** 51 | * @return The largest @c int less than the @c double @c x. This macro is needed to avoid 52 | * rounding errors when "modules" project setting is enabled causing math functions to 53 | * map from tgmath.h to math.h. 54 | */ 55 | #define grey_floor(x) ((CGFloat)floor(x)) 56 | 57 | #endif // GREY_DEFINES_H 58 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYDescription.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * A protocol that defines the layout of an object that conforms to GREYMatcher. 23 | */ 24 | @protocol GREYDescription 25 | 26 | /** 27 | * Appends the provided text to the GREYDescription. 28 | * 29 | * @param text The text to be appended to the GREYDescription. 30 | * 31 | * @return An instance of an object conforming to GREYDescription with the provided 32 | * @c text appended to it. 33 | */ 34 | - (id)appendText:(NSString *)text; 35 | 36 | /** 37 | * Appends the description of the provided object to the GREYDescription. 38 | * 39 | * @param object The object whose description is to be appended to the GREYDescription. 40 | * 41 | * @return An instance of an object conforming to GREYDescription with the provided 42 | * object's description appended to it. 43 | */ 44 | - (id)appendDescriptionOf:(id)object; 45 | 46 | @end 47 | 48 | NS_ASSUME_NONNULL_END 49 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYDispatchQueueIdlingResource.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * Idling resource that tracks blocks sent to a dispatch queue. 23 | */ 24 | @interface GREYDispatchQueueIdlingResource : NSObject 25 | 26 | /** 27 | * Creates an idling resource backed by the specified @c queue. 28 | * 29 | * @c dispatch_sync blocks and dispatch_sync_f tasks sent to @c queue are tracked. 30 | * @c dispatch_async blocks and @c dispatch_async_f tasks sent to @c queue are tracked. 31 | * @c dispatch_after blocks and @c dispatch_after_f tasks sent to @c queue are tracked if they are 32 | * delayed no more than the delay amount set for the 33 | * @c kGREYConfigKeyTrackableDispatchAfterDuration configuration. A weak reference is held to 34 | * @c queue. If @c queue is deallocated, then the idling resource will deregister itself from the 35 | * UI thread executor. 36 | * 37 | * @param queue The dispatch queue that will be tracked by the resource. 38 | * @param name A descriptive name for the idling resource. 39 | * 40 | * @return An idling resource backed by the specified dispatch queue. 41 | */ 42 | + (instancetype)resourceWithDispatchQueue:(dispatch_queue_t)queue name:(NSString *)name; 43 | 44 | /** 45 | * @remark init is not an available initializer. Use the other initializers. 46 | */ 47 | - (instancetype)init NS_UNAVAILABLE; 48 | 49 | @end 50 | 51 | NS_ASSUME_NONNULL_END 52 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYElementFinder.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | @protocol GREYMatcher, GREYProvider; 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | /** 24 | * Finds UI elements in GREYProvider that are accepted by a matcher. 25 | */ 26 | @interface GREYElementFinder : NSObject 27 | 28 | /** 29 | * The matcher the element finder is initialized with. Objects returned from this class 30 | * must match this matcher. 31 | */ 32 | @property(nonatomic, readonly) id matcher; 33 | 34 | /** 35 | * @remark init is not an available initializer. Use the other initializers. 36 | */ 37 | - (instancetype)init NS_UNAVAILABLE; 38 | 39 | /** 40 | * Initializes the finder with a given @c matcher. 41 | * 42 | * @param matcher Matcher that defines what elements the finder should search for. 43 | * 44 | * @return An instance of GREYElementFinder, initialized with a matcher. 45 | */ 46 | - (instancetype)initWithMatcher:(id)matcher NS_DESIGNATED_INITIALIZER; 47 | 48 | /** 49 | * Performs a search on elements provided by @c elementProvider and returns all the elements 50 | * that are accepted by the matcher this object is initialized with. 51 | * 52 | * @param elementProvider Provides elements to run through the matcher. 53 | * 54 | * @return An array of matched elements. If no matching element is found, then it is empty. 55 | * The relative order of the elements is preserved when returned. 56 | */ 57 | - (NSArray *)elementsMatchedInProvider:(id)elementProvider; 58 | 59 | @end 60 | 61 | NS_ASSUME_NONNULL_END 62 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYElementHierarchy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * A utility to get the string representation of the UI hierarchy. 23 | */ 24 | @interface GREYElementHierarchy : NSObject 25 | 26 | /** 27 | * Returns UI hierarchy with @c element as the root. @c element can be either a UIView or an 28 | * Accessibility element. 29 | * 30 | * @param element The root element for the hierarchy. 31 | * 32 | * @return The UI hierarchy as a string. 33 | */ 34 | + (NSString *)hierarchyStringForElement:(id)element; 35 | 36 | /** 37 | * Similar to hierarchyStringForElement: with additional parameters for providing annotations 38 | * for printed views. @c annotationDictionary is a dictionary of type 39 | * @code @{[NSValue valueWithNonretainedObject:id]:NSString} @endcode with UI elements that 40 | * require special formatting i.e. special text to be appended to the description. For example, 41 | * @code @{viewA : @"This is a special view"} @endcode or 42 | * @code @{elementA : @"This is a special view"} @endcode will have it's description as: 43 | * @" This is a special view". 44 | * 45 | * @param element The root element for the hierarchy. 46 | * @param annotationDictionary A dictionary of annotations. 47 | * 48 | * @return The UI hierarchy as a string. 49 | */ 50 | + (NSString *)hierarchyStringForElement:(id)element 51 | withAnnotationDictionary:(NSDictionary *_Nullable)annotationDictionary; 52 | 53 | /** 54 | * Returns the UI hierarchy for all @c UIWindows provided by the GREYUIWindowProvider. 55 | */ 56 | + (NSString *)hierarchyStringForAllUIWindows; 57 | 58 | @end 59 | 60 | NS_ASSUME_NONNULL_END 61 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYElementInteraction.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | #import 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | /** 24 | * Interface for creating an interaction with a UI element. If no datasource is set, 25 | * a default datasource is used. The default datasource provides access to the entire UI element 26 | * hierarchy of all the windows in the application. 27 | */ 28 | @interface GREYElementInteraction : NSObject 29 | 30 | /** 31 | * @remark init is not an available initializer. Use the other initializers. 32 | */ 33 | - (instancetype)init NS_UNAVAILABLE; 34 | 35 | /** 36 | * Initializes the interaction with a single UI element matching @c elementMatcher. 37 | * 38 | * @param elementMatcher Matcher for selecting UI element to interact with. 39 | * 40 | * @return An instance of GREYElementInteraction, initialized with a specified matcher. 41 | */ 42 | - (instancetype)initWithElementMatcher:(id)elementMatcher; 43 | 44 | @end 45 | 46 | NS_ASSUME_NONNULL_END 47 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYFailureHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | @class GREYFrameworkException; 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | /** 24 | * Protocol for handling failures (such as failure of actions and assertions) raised by EarlGrey. 25 | */ 26 | @protocol GREYFailureHandler 27 | 28 | /** 29 | * Called by the framework to raise an exception. 30 | * 31 | * @param exception The exception to be handled. 32 | * @param details Extra information about the failure. 33 | */ 34 | - (void)handleException:(GREYFrameworkException *)exception details:(NSString *)details; 35 | 36 | @optional 37 | 38 | /** 39 | * Sets the file name and line number of operation that caused the failure. 40 | * 41 | * @param fileName The name of the file where the error happened. 42 | * @param lineNumber The line number in the file that caused the error. 43 | */ 44 | - (void)setInvocationFile:(NSString *)fileName andInvocationLine:(NSUInteger)lineNumber; 45 | 46 | @end 47 | 48 | NS_ASSUME_NONNULL_END 49 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYIdlingResource.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * A protocol for resources that can potentially modify the UI and should be synchronized with 23 | * before performing any interaction or verification with UI element. 24 | */ 25 | @protocol GREYIdlingResource 26 | 27 | /** 28 | * A method to query idleness of this resource. 29 | * 30 | * Note: This method is called on the main thread and polled continuously until this resource goes 31 | * into idle state or a test timeout occurs. It is discouraged to perform any heavy tasks in this 32 | * method. 33 | * 34 | * @return @c YES if the resource is currently idle; @c NO otherwise. 35 | */ 36 | - (BOOL)isIdleNow; 37 | 38 | /** 39 | * @return A user friendly name that will be printed if this resource fails to idle leading to a 40 | * test timeout. 41 | */ 42 | - (NSString *)idlingResourceName; 43 | 44 | /** 45 | * @return Information that will be printed alongside the name if this resource fails to idle in 46 | * the given timeout. 47 | */ 48 | - (NSString *)idlingResourceDescription; 49 | 50 | @end 51 | 52 | NS_ASSUME_NONNULL_END 53 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYManagedObjectContextIdlingResource.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | @class NSManagedObjectContext; 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | /** 24 | * Idling resource that tracks core data managed object context operations. 25 | * 26 | * Tracks the managed object context's internal operation queue and optionally any pending changes 27 | * yet to be committed. 28 | */ 29 | @interface GREYManagedObjectContextIdlingResource : NSObject 30 | 31 | /** 32 | * Creates an idling resource tracking @c managedObjectContext. 33 | * 34 | * A weak reference is held to @c managedObjectContext. If @c managedObjectContext is deallocated, 35 | * then the idling resource will deregister itself from the thread executor. 36 | * 37 | * @param managedObjectContext The managed object context to be tracked by the resource. 38 | * @param trackPendingChanges If @c YES, then the idling resource will report that it is busy 39 | * when the managed object context has pending changes. 40 | * @param name A descriptive name for the idling resource. 41 | * 42 | * @return An idling resource tracking @c managedObjectContext. 43 | */ 44 | + (instancetype)resourceWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext 45 | trackPendingChanges:(BOOL)trackPendingChanges 46 | name:(NSString *)name; 47 | 48 | /** 49 | * @remark init is not an available initializer. Use the other initializers. 50 | */ 51 | - (instancetype)init NS_UNAVAILABLE; 52 | 53 | @end 54 | 55 | NS_ASSUME_NONNULL_END 56 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | #import 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | /** 24 | * Matchers are another way of expressing simple or complex logical expressions. This protocol 25 | * defines a set of methods that must be implemented by every matcher object. 26 | */ 27 | @protocol GREYMatcher 28 | 29 | /** 30 | * A method to evaluate the matcher for the provided @c item. 31 | * 32 | * @param item The object which is to be evaluated against the matcher. 33 | * 34 | * @return @c YES if the object matched the matcher, @c NO otherwise. 35 | */ 36 | - (BOOL)matches:(_Nullable id)item; 37 | 38 | /** 39 | * A method to evaluate the matcher for the provided @c item with a description for the issue 40 | * in case of a mismatch. 41 | * 42 | * @param item The object which is to be evaluated against the matcher. 43 | * 44 | * @param mismatchDescription The description that is built or appended if the provided @c item 45 | * does not match the matcher. 46 | * 47 | * @return @c YES if the object matched the matcher, @c NO otherwise. In case of a mismatch, the 48 | * reason for mismatch is added to @c mismatchDescription. 49 | */ 50 | - (BOOL)matches:(_Nullable id)item describingMismatchTo:(id)mismatchDescription; 51 | 52 | /** 53 | * A method to generate the description containing the reason for why a matcher did not match an 54 | * item. 55 | * 56 | * @param item The object which is to be evaluated against the matcher. 57 | * 58 | * @param mismatchDescription The description that is built or appended if the provided @c item 59 | * does not match the matcher. 60 | * 61 | * @remark This method assumes that GREYMatcher::matches: is false, but will not check this. 62 | */ 63 | - (void)describeMismatchOf:(_Nullable id)item to:(id)mismatchDescription; 64 | 65 | /** 66 | * A method to generate a description of an object. 67 | * 68 | * @param description The description that is built or appended. 69 | */ 70 | - (void)describeTo:(id)description; 71 | 72 | @end 73 | 74 | NS_ASSUME_NONNULL_END 75 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYNSTimerIdlingResource.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * An idling resource to track NSTimer firing events so that the framework can synchronize 23 | * with them. 24 | */ 25 | @interface GREYNSTimerIdlingResource : NSObject 26 | 27 | /** 28 | * @remark init is not an available initializer. Use the other initializers. 29 | */ 30 | - (instancetype)init NS_UNAVAILABLE; 31 | 32 | /** 33 | * Creates an idling resource that tracks the specified @c timer, causing actions to wait until 34 | * the timer is fired or invalidated. If @c removeOnIdle is @c YES, the idling resource will 35 | * automatically remove itself from the list of registered idling resources when it becomes idle. 36 | * 37 | * @param timer The timer that will be tracked by the idling resource. 38 | * @param name A descriptive name for the idling resource. 39 | * @param removeOnIdle Defines whether the resource should unregister itself when it becomes idle. 40 | * 41 | * @return A new and initialized GREYNSTimerIdlingResource instance. 42 | */ 43 | + (instancetype)trackTimer:(NSTimer *)timer name:(NSString *)name removeOnIdle:(BOOL)removeOnIdle; 44 | 45 | @end 46 | 47 | NS_ASSUME_NONNULL_END 48 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYNot.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | #import 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | /** 23 | * A matcher to negate the result of another matcher. 24 | */ 25 | @interface GREYNot : GREYBaseMatcher 26 | 27 | /** 28 | * @remark init is not an available initializer. Use the other initializers. 29 | */ 30 | - (instancetype)init NS_UNAVAILABLE; 31 | 32 | /** 33 | * Initializes this matcher with another @c matcher whose result is negated. 34 | * 35 | * @param matcher A matcher whose result will be negated. 36 | * 37 | * @return An instance of GREYNot, initialized with a matcher. 38 | */ 39 | - (instancetype)initWithMatcher:(id)matcher NS_DESIGNATED_INITIALIZER; 40 | 41 | #if !(GREY_DISABLE_SHORTHAND) 42 | 43 | /** Shorthand macro for GREYNot::initWithMatcher:. */ 44 | GREY_EXPORT id grey_not(id matcher); 45 | 46 | #endif // GREY_DISABLE_SHORTHAND 47 | 48 | @end 49 | 50 | NS_ASSUME_NONNULL_END 51 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYOperationQueueIdlingResource.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * Idling resource that monitors operation queues. 23 | */ 24 | @interface GREYOperationQueueIdlingResource : NSObject 25 | 26 | /** 27 | * Creates an idling resource for monitoring @c queue for idleness. 28 | * A queue is considered idle when it has no pending operations. 29 | * A weak reference is held to @c queue. If @c queue is deallocated, then the idling resource will 30 | * deregister itself from the UI thread executor. 31 | * 32 | * @param queue The queue that will be tracked by the resource. 33 | * @param name A descriptive name for the idling resource. 34 | * 35 | * @return Returns an idling resource for the specified NSOperationQueue. 36 | */ 37 | + (instancetype)resourceWithNSOperationQueue:(NSOperationQueue *)queue name:(NSString *)name; 38 | 39 | /** 40 | * @remark init is not an available initializer. Use the other initializers. 41 | */ 42 | - (instancetype)init NS_UNAVAILABLE; 43 | 44 | @end 45 | 46 | NS_ASSUME_NONNULL_END 47 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYProvider.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * A protocol for providing arbitrary data as an enumeration. 23 | */ 24 | @protocol GREYProvider 25 | 26 | /** 27 | * @return A new enumerator that can be used to enumerate data backed by this provider. 28 | */ 29 | - (NSEnumerator *)dataEnumerator; 30 | 31 | @end 32 | 33 | NS_ASSUME_NONNULL_END 34 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYScrollActionError.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | #import 20 | 21 | /** 22 | * The Error domain for a scroll error. 23 | */ 24 | GREY_EXTERN NSString *const kGREYScrollErrorDomain; 25 | 26 | /** 27 | * Error codes for scrolling related errors. 28 | */ 29 | typedef NS_ENUM(NSInteger, GREYScrollErrorCode) { 30 | /** 31 | * Reached content edge before the entire scroll action was complete. 32 | */ 33 | kGREYScrollReachedContentEdge, 34 | /** 35 | * It is not possible to scroll. 36 | */ 37 | kGREYScrollImpossible, 38 | /** 39 | * Could not scroll to the element we are looking for. 40 | */ 41 | kGREYScrollToElementFailed, 42 | }; 43 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYSyncAPI.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | #import 20 | 21 | /** 22 | * @file 23 | * @brief Methods for executing sync or async blocks with EarlGrey operations. 24 | */ 25 | 26 | NS_ASSUME_NONNULL_BEGIN 27 | 28 | /** 29 | * Executes a block containing EarlGrey statements on the main thread and waits for it to 30 | * complete. @c block is retained until execution completes. 31 | * Important: Must be called from a non-main thread otherwise it will block main thread 32 | * indefinitely. 33 | * 34 | * @param block Block that will be executed. 35 | */ 36 | GREY_EXPORT void grey_execute_sync(void (^block)(void)); 37 | 38 | /** 39 | * Executes a block containing EarlGrey statements on the main thread without waiting for it to 40 | * complete. @c block is retained until execution completes. 41 | * Can be invoked safely from the main or non-main thread. 42 | * 43 | * @param block Block that will be executed. 44 | */ 45 | GREY_EXPORT void grey_execute_async(void (^block)(void)); 46 | 47 | NS_ASSUME_NONNULL_END 48 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Headers/GREYTestHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * Provides interface for test helper methods. 23 | */ 24 | @interface GREYTestHelper : NSObject 25 | 26 | /** 27 | * Enables fast animation. Invoke in the XCTest setUp method to increase 28 | * the speed of your tests by not having to wait on slow animations. 29 | */ 30 | + (void)enableFastAnimation; 31 | 32 | /** 33 | * Disables fast animation. 34 | */ 35 | + (void)disableFastAnimation; 36 | 37 | @end 38 | 39 | NS_ASSUME_NONNULL_END 40 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgl0v/TMDB/5fc1aec6e6552f03d90809d0b672d490b8b7759a/TMDBTests/Frameworks/EarlGrey.framework/Info.plist -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module EarlGrey { 2 | umbrella header "EarlGrey.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/CAAnimation+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | /** 20 | * An enumeration of all states that EarlGrey identifies a CAAnimation to be in. 21 | */ 22 | typedef NS_ENUM(NSUInteger, GREYCAAnimationState) { 23 | /** 24 | * Default state every animation is in. 25 | */ 26 | kGREYAnimationPendingStart = 0, 27 | /** 28 | * State the animation is in when it begins. 29 | */ 30 | kGREYAnimationStarted, 31 | /** 32 | * State the animation is in when it ends. 33 | */ 34 | kGREYAnimationStopped, 35 | }; 36 | 37 | NS_ASSUME_NONNULL_BEGIN 38 | 39 | /** 40 | * EarlGrey specific addition for CAAnimation to track currently running animations. 41 | */ 42 | @interface CAAnimation (GREYAdditions) 43 | 44 | /** 45 | * Sets the animation state to @c state. 46 | * 47 | * @param state The target state. 48 | */ 49 | - (void)grey_setAnimationState:(GREYCAAnimationState)state; 50 | 51 | /** 52 | * Returns the current state of the animation. If CAAnimation::grey_setAnimationState was never 53 | * called on this animation, @c kGREYANIMATION_PENDING_START is returned. 54 | * 55 | * @return The current state. 56 | */ 57 | - (GREYCAAnimationState)grey_animationState; 58 | 59 | /** 60 | * Tracks the animation with GREYAppStateTracker until the expected animation runtime has elapsed, 61 | * after which it untracks itself. 62 | */ 63 | - (void)grey_trackForDurationOfAnimation; 64 | 65 | /** 66 | * Force untrack itself from GREYAppStateTracker, regardless of completion status. 67 | */ 68 | - (void)grey_untrack; 69 | 70 | @end 71 | 72 | NS_ASSUME_NONNULL_END 73 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/CALayer+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | /** 20 | * EarlGrey specific additions to CALayer to track animations. 21 | */ 22 | @interface CALayer (GREYAdditions) 23 | @end 24 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYActions+Internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | /** 18 | * @file GREYActions+Internal.h 19 | * @brief Exposes GREYActions' interfaces and methods that are otherwise private for 20 | * testing purposes. 21 | */ 22 | 23 | NS_ASSUME_NONNULL_BEGIN 24 | 25 | @interface GREYActions (Internal) 26 | 27 | /** 28 | * Use the iOS keyboard to type a string starting from the provided UITextPosition. If the 29 | * position is @c nil, then type text from the text input's current position. Should only be called 30 | * with a position if element conforms to the UITextInput protocol - which it should if you 31 | * derived the UITextPosition from the element. 32 | * 33 | * @param text The text to be typed. 34 | * @param position The position in the text field at which the text is to be typed. 35 | * 36 | * @return @c YES if the action succeeded, else @c NO. If an action returns @c NO, it does not 37 | * mean that the action was not performed at all but somewhere during the action execution 38 | * the error occurred and so the UI may be in an unrecoverable state. 39 | * 40 | * @remark This is available only for internal testing purposes. 41 | */ 42 | + (id)grey_actionForTypeText:(NSString *)text 43 | atUITextPosition:(UITextPosition *)position; 44 | @end 45 | 46 | NS_ASSUME_NONNULL_END 47 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYAnalytics.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | @protocol GREYAnalyticsDelegate; 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | /** 24 | * Provides methods for tracking EarlGrey usage using Google Analytics. 25 | * 26 | * @remark To opt out of Analytics use GREYConfiguration and set config value for 27 | * @c kGREYConfigKeyAnalyticsEnabled to @c NO before the instance tear down method 28 | * XCTestCase::tearDown method returns. Sample code to opt out of analytics: 29 | * @code 30 | * [[GREYConfiguration sharedInstance] setValue:@(NO) 31 | * forConfigKey:kGREYConfigKeyAnalyticsEnabled]; 32 | * @endcode 33 | */ 34 | @interface GREYAnalytics : NSObject 35 | 36 | /** 37 | * @return The singleton instance. 38 | */ 39 | + (instancetype)sharedInstance; 40 | 41 | /** 42 | * @return The current delegate. 43 | */ 44 | - (id)delegate; 45 | 46 | /** 47 | * Sets a delegate for custom handling of analytics payload data. To reset GREYAnalytics to its 48 | * default behavior pass @c nil. 49 | */ 50 | - (void)setDelegate:(id)delegate; 51 | 52 | /** 53 | * Called when an EarlGrey invocation occurs using any @code [EarlGrey XXX] @endcode statements. 54 | */ 55 | - (void)didInvokeEarlGrey; 56 | 57 | /** 58 | * Sends an Analytics Event hit based on protocol specified in: 59 | * @see https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide#event 60 | * 61 | * @param trackingID The tracking ID under which to track this event. 62 | * @param clientID The ID for the user sending this event. 63 | * @param category The Event Category for the event hit. 64 | * @param action The Event Action for the event hit. 65 | * @param value The event value for the event hit. 66 | */ 67 | + (void)sendEventHitWithTrackingID:(NSString *)trackingID 68 | clientID:(NSString *)clientID 69 | category:(NSString *)category 70 | action:(NSString *)action 71 | value:(NSString *)value; 72 | 73 | @end 74 | 75 | NS_ASSUME_NONNULL_END 76 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYAnalyticsDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | @protocol GREYAnalyticsDelegate 22 | 23 | /** 24 | * Sent to the delegate to handle Analytics Event hit. See this for more info: 25 | * https://developers.google.com/analytics/devguides/collection/protocol/v1/. 26 | * 27 | * @note In case of failure to track the method must fail silently to prevent test interruption. 28 | * 29 | * @param trackingID The tracking ID under which to track this event. 30 | * @param clientID The ID for the user sending this event. 31 | * @param category The Event Category for the event hit. 32 | * @param action The Event Action for the event hit. 33 | * @param value The event value for the event hit. 34 | */ 35 | - (void)trackEventWithTrackingID:(NSString *)trackingID 36 | clientID:(NSString *)clientID 37 | category:(NSString *)category 38 | action:(NSString *)action 39 | value:(NSString *)value; 40 | 41 | @end 42 | 43 | NS_ASSUME_NONNULL_END 44 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYAppStateTrackerObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | #import "Synchronization/GREYAppStateTracker.h" 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | @class GREYObjectDeallocationTracker; 24 | 25 | /** 26 | * Class used by the GREYAppStateTracker for synchronization purposes. 27 | */ 28 | @interface GREYAppStateTrackerObject : NSObject 29 | 30 | /** 31 | * Initializing the GREYAppStateTrackerObject. 32 | * 33 | * @param deallocationTracker The object that will be pointed to using a weak reference. 34 | * 35 | * @return An instance of GREYAppStateTrackerObject. 36 | */ 37 | - (instancetype)initWithDeallocationTracker:(GREYObjectDeallocationTracker *)deallocationTracker; 38 | 39 | /** 40 | * @remark init is not an available initializer. Use the other initializer. 41 | */ 42 | - (instancetype)init NS_UNAVAILABLE; 43 | 44 | /** 45 | * @c object is an instance of GREYObjectDeallocatingTracker aka the internal object. The 46 | * GREYAppStateTrackerObject holds weakly to the GREYObjectDeallocatingTracker object. 47 | */ 48 | @property(nonatomic, readonly, weak) GREYObjectDeallocationTracker *object; 49 | 50 | /** 51 | * The state that this object is tracking. 52 | */ 53 | @property(nonatomic, assign) GREYAppState state; 54 | 55 | /** 56 | * The description of the object that is being represented by GREYAppStateTrackerObject. 57 | */ 58 | @property(nonatomic, strong) NSString *objectDescription; 59 | 60 | /** 61 | * @return The callstack that was set when a new state @c state was set. 62 | */ 63 | - (NSArray *)stateAssignmentCallStack; 64 | 65 | @end 66 | 67 | NS_ASSUME_NONNULL_END 68 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYAssertions+Internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | /** 18 | * @file GREYAssertions+Internal.h 19 | * @brief Exposes GREYAssertions' interfaces and methods that are otherwise private for 20 | * testing purposes. 21 | */ 22 | 23 | #import 24 | 25 | @class GREYError; 26 | @protocol GREYAssertion; 27 | @protocol GREYMatcher; 28 | 29 | @interface GREYAssertions (Internal) 30 | 31 | /** 32 | * Raise a @c GREYFrameworkException with the provided @c name, @c details and @c error. 33 | * 34 | * @param name The name of the exception. 35 | * @param details The details of the exception. 36 | * @param error The error that is the major reason of the exception. 37 | * 38 | * @remark This is available only for internal usage purposes. 39 | */ 40 | + (void)grey_raiseExceptionNamed:(NSString *)name 41 | exceptionDetails:(NSString *)details 42 | withError:(GREYError *)error; 43 | 44 | /** 45 | * Create a @c GREYAssertion with the provided @c matcher to check assertions on elements. 46 | * 47 | * @param matcher The @c GREYMatcher object to be matched by the assertion. 48 | * 49 | * @return A @c GREYAssertion object that can be used to match an object with the provided @c matcher. 50 | * 51 | * @remark This is available only for internal testing purposes. 52 | */ 53 | + (id)grey_createAssertionWithMatcher:(id)matcher; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYCAAnimationDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | #import 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | @interface GREYCAAnimationDelegate : NSObject 23 | 24 | /** 25 | * Wraps the passed in CAAnimationDelegate in a GREYSurrogateDelegate for helping in tracking 26 | * the delegate's animation start and stop events for better synchronization. 27 | * 28 | * @param delegate The CAAnimationDelegate animation delegate that is to be swizzled. 29 | * 30 | * @return An NSObject conforming to CAAnimationDelegate. 31 | */ 32 | + (instancetype)surrogateDelegateForDelegate:(id)delegate; 33 | 34 | /** 35 | * @remark init is not an available initializer. Use surrogateDelegateForDelegate. 36 | */ 37 | - (instancetype)init NS_UNAVAILABLE; 38 | 39 | #pragma mark - CAAnimationDelegate 40 | 41 | - (void)animationDidStart:(CAAnimation *)animation; 42 | - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished; 43 | 44 | @end 45 | 46 | NS_ASSUME_NONNULL_END 47 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYChangeStepperAction.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * Actions for manipulating UIStepper. 23 | */ 24 | @interface GREYChangeStepperAction : GREYBaseAction 25 | 26 | /** 27 | * @remark init is not an available initializer. Use the other initializers. 28 | */ 29 | - (instancetype)init NS_UNAVAILABLE; 30 | 31 | /** 32 | * @remark initWithName::constraints: is overridden from its superclass. 33 | */ 34 | - (instancetype)initWithName:(NSString *)name 35 | constraints:(id)constraints NS_UNAVAILABLE; 36 | 37 | /** 38 | * Initializes with the expected value by which to change the stepper. 39 | * 40 | * @param value The amount by which the stepper should change. 41 | * 42 | * @return An instance of GREYChangeStepperAction. 43 | */ 44 | - (instancetype)initWithValue:(double)value NS_DESIGNATED_INITIALIZER; 45 | 46 | @end 47 | 48 | NS_ASSUME_NONNULL_END 49 | 50 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYElementInteraction+Internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | /** 18 | * @file GREYElementInteraction+Internal.h 19 | * @brief Exposes GREYElementInteraction's interfaces and methods that are otherwise private for 20 | * testing purposes. 21 | */ 22 | 23 | #import 24 | 25 | NS_ASSUME_NONNULL_BEGIN 26 | 27 | @interface GREYElementInteraction (Internal) 28 | 29 | /** 30 | * Searches for UI elements within the root views and returns all matched UI elements. The given 31 | * search action is performed until an element is found. 32 | * 33 | * @param timeout The amount of time during which search actions must be performed to find an 34 | * element. 35 | * @param error The error populated on failure. If an element was found and returned when using 36 | * the search actions then any action or timeout errors that happened in the 37 | * previous search are ignored. However, if an element is not found, the error 38 | * will be propagated. 39 | * 40 | * @return An array of matched UI elements in the data source. If no UI element is found in 41 | * @c timeout seconds, a timeout error will be produced and no UI element will be returned. 42 | * 43 | * @remark This is available only for internal testing purposes. 44 | */ 45 | - (NSArray *)matchedElementsWithTimeout:(NSTimeInterval)timeout error:(__strong NSError **)error; 46 | 47 | @end 48 | 49 | NS_ASSUME_NONNULL_END 50 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYErrorConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | /** 20 | * Extern variables specifying the error keys for a base action. 21 | */ 22 | GREY_EXTERN NSString *const kErrorDetailElementDescriptionKey; 23 | GREY_EXTERN NSString *const kErrorDetailConstraintRequirementKey; 24 | GREY_EXTERN NSString *const kErrorDetailConstraintDetailsKey; 25 | 26 | /** 27 | * Extern variables specifying the error domain for GREYElementInteraction. 28 | */ 29 | GREY_EXTERN NSString *const kGREYInteractionErrorDomain; 30 | GREY_EXTERN NSString *const kGREYWillPerformActionNotification; 31 | GREY_EXTERN NSString *const kGREYDidPerformActionNotification; 32 | GREY_EXTERN NSString *const kGREYWillPerformAssertionNotification; 33 | GREY_EXTERN NSString *const kGREYDidPerformAssertionNotification; 34 | 35 | /** 36 | * Extern variables specifying the user info keys for any notifications. 37 | */ 38 | GREY_EXTERN NSString *const kGREYActionUserInfoKey; 39 | GREY_EXTERN NSString *const kGREYActionElementUserInfoKey; 40 | GREY_EXTERN NSString *const kGREYActionErrorUserInfoKey; 41 | GREY_EXTERN NSString *const kGREYAssertionUserInfoKey; 42 | GREY_EXTERN NSString *const kGREYAssertionElementUserInfoKey; 43 | GREY_EXTERN NSString *const kGREYAssertionErrorUserInfoKey; 44 | 45 | /** 46 | * Internal variables specifying the detail keys for error details. 47 | */ 48 | GREY_EXTERN NSString *const kErrorDetailElementMatcherKey; 49 | 50 | /** 51 | * The error domain for pinch action related errors. 52 | */ 53 | GREY_EXTERN NSString *const kGREYPinchErrorDomain; 54 | 55 | /** 56 | * Extern variables specifying the user info keys for a pinch action. 57 | */ 58 | GREY_EXTERN NSString *const kErrorDetailElementKey; 59 | GREY_EXTERN NSString *const kErrorDetailWindowKey; 60 | 61 | /** 62 | * Extern variables specifying the error keys for a change stepper action. 63 | */ 64 | GREY_EXTERN NSString *const kErrorDetailStepperKey; 65 | GREY_EXTERN NSString *const kErrorDetailUserValueKey; 66 | GREY_EXTERN NSString *const kErrorDetailStepMaxValueKey; 67 | GREY_EXTERN NSString *const kErrorDetailStepMinValueKey; 68 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYFailureScreenshotter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | @interface GREYFailureScreenshotter : NSObject 22 | 23 | /** 24 | * Generate app screenshot with given prefix and failure name. 25 | * 26 | * @param screenshotPrefix Prefix for the screenshots. 27 | * @param failureName Failure name associated with the screenshots. 28 | * 29 | * @return A dictionary of the screenshot names and their corresponding paths. 30 | */ 31 | 32 | + (NSDictionary *)generateAppScreenshotsWithPrefix:(NSString *_Nullable)screenshotPrefix 33 | failure:(NSString *)failureName; 34 | 35 | /** 36 | * Generate app screenshot with given prefix and failure name. 37 | * 38 | * @param screenshotPrefix Prefix for the screenshots. 39 | * @param failureName Failure name associated with the screenshots. 40 | * @param screenshotDir The screenshot directory where the screenshots are placed. 41 | * 42 | * @return A dictionary of the screenshot names and their corresponding paths. 43 | */ 44 | + (NSDictionary *)generateAppScreenshotsWithPrefix:(NSString *_Nullable)screenshotPrefix 45 | failure:(NSString *)failureName 46 | screenshotDir:(NSString *)screenshotDir; 47 | 48 | @end 49 | 50 | NS_ASSUME_NONNULL_END 51 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYInteractionDataSource.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | @protocol GREYProvider; 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * Provides data to a GREYInteraction. 23 | */ 24 | @protocol GREYInteractionDataSource 25 | 26 | /** 27 | * The root element provider for an interaction. The entire hierarchies starting from the root 28 | * elements are searched to find the right element to interact with. 29 | * 30 | * @return A GREYProvider instance providing data for the interaction. 31 | */ 32 | - (id)rootElementProvider; 33 | 34 | @end 35 | 36 | NS_ASSUME_NONNULL_END 37 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYKeyboard.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * Provides ability to perform input actions using the iOS system keyboard and also track the 23 | * current keyboard visibility. 24 | */ 25 | @interface GREYKeyboard : NSObject 26 | 27 | /** 28 | * Types @c string using the keyboard in the provided @c firstResponder. Keyboard must be shown 29 | * on the screen when this method is called. 30 | * 31 | * @param string Text to be typed using the keyboard. 32 | * @param firstResponder The element that the text is to be typed in. 33 | * @param[out] errorOrNil Error populated when any failure occurs during typing. If @c nil, then a 34 | * custom error with @c kGREYInteractionActionFailedErrorCode is logged. 35 | * 36 | * @return @c YES if typing succeeded, @c NO otherwise. 37 | */ 38 | + (BOOL)typeString:(NSString *)string 39 | inFirstResponder:(id)firstResponder 40 | error:(__strong NSError **)errorOrNil; 41 | 42 | /** 43 | * Waits until the keyboard is visible on the screen. 44 | * @return @c YES if the keyboard did appear after the wait, @c NO otherwise. 45 | */ 46 | + (BOOL)waitForKeyboardToAppear; 47 | 48 | /** 49 | * @return @c YES if the keyboard is present on the screen, @c NO otherwise. 50 | */ 51 | + (BOOL)isKeyboardShown; 52 | 53 | @end 54 | 55 | NS_ASSUME_NONNULL_END 56 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYLogger.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | /** 18 | * @file GREYLogger.h 19 | * @brief Macro for printing more logs for aiding in debugging. 20 | */ 21 | 22 | #import 23 | 24 | /** 25 | * Prints a log statement if @c kGREYAllowVerboseLogging is present and turned to @c YES in 26 | * @c NSUserDefaults. You can pass it in the command line arguments as: 27 | * To turn on, set @c kGREYAllowVerboseLogging key in @c NSUserDefaults to @c YES. 28 | * @code 29 | * [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kGREYAllowVerboseLogging]; 30 | * @endcode 31 | * 32 | * @remark Once you set this, as with any @c NSUserDefault, you need to explicitly turn it off 33 | * or delete and re-install the app under test. 34 | * 35 | * @param format The string format to be printed. 36 | * @param ... The parameters to be added to the string format. 37 | */ 38 | #define GREYLogVerbose(format, ...) \ 39 | ({ \ 40 | if ([[NSUserDefaults standardUserDefaults] boolForKey:kGREYAllowVerboseLogging]) { \ 41 | NSLog((format), ##__VA_ARGS__); \ 42 | } \ 43 | }) 44 | 45 | 46 | /** 47 | * Log an error generated by the system or EarlGrey to the console. 48 | * 49 | * @param error An error object to be logged. This can be an @c NSError object or 50 | * a @c GREYError object. 51 | * 52 | */ 53 | #define GREYLogError(error) \ 54 | ({ \ 55 | I_GREYLogError(error, \ 56 | [NSString stringWithUTF8String:__FILE__], \ 57 | __LINE__, \ 58 | [NSString stringWithUTF8String:__PRETTY_FUNCTION__], \ 59 | [NSThread callStackSymbols]); \ 60 | }) 61 | 62 | NS_ASSUME_NONNULL_BEGIN 63 | 64 | /** 65 | * Log an error generated by the system or EarlGrey to the console. 66 | */ 67 | GREY_EXPORT void I_GREYLogError(NSError *error, 68 | NSString *filePath, 69 | NSUInteger lineNumber, 70 | NSString *functionName, 71 | NSArray *stackTrace); 72 | 73 | NS_ASSUME_NONNULL_END 74 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYNSURLConnectionDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | #import "Delegate/GREYSurrogateDelegate.h" 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | /** 24 | * This is a proxy delegate for NSURLConnectionDelegate which allows us track status of 25 | * the connection. 26 | * 27 | * @todo Support NSURLConnectionDownloadDelegate. 28 | */ 29 | @interface GREYNSURLConnectionDelegate : GREYSurrogateDelegate 30 | 31 | 32 | /** 33 | * @remark init is not an available initializer. Use the other initializers. 34 | */ 35 | - (instancetype)init NS_UNAVAILABLE; 36 | 37 | /** 38 | * Creates an instance of GREYNSURLConnectionDelegate backed by the provided delegate. 39 | * 40 | * @param originalDelegate The original delegate being proxied. 41 | * @return an instance of GREYNSURLConnectionDelegate backed by the original delegate. 42 | */ 43 | - (instancetype)initWithOriginalNSURLConnectionDelegate:(id)originalDelegate; 44 | 45 | @end 46 | 47 | NS_ASSUME_NONNULL_END 48 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYObjcRuntime.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * A utility class used for common runtime related operations. 23 | */ 24 | @interface GREYObjcRuntime : NSObject 25 | 26 | /** 27 | * Adds the given method from the given class into the destination class. 28 | * 29 | * @param destination The destination class. 30 | * @param selector The method selector from source class that needs to be added to destination. 31 | * @param source The source class for the method to be added. 32 | */ 33 | + (void)addInstanceMethodToClass:(Class)destination 34 | withSelector:(SEL)selector 35 | fromClass:(Class)source; 36 | 37 | @end 38 | 39 | NS_ASSUME_NONNULL_END 40 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYObjectDeallocationTracker.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | @class GREYObjectDeallocationTracker; 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | @protocol GREYObjectDeallocationTrackerDelegate 24 | 25 | /** 26 | * Delegate method that is called when the GREYObjectDeallocationTracker is deallocated. 27 | * 28 | * @param objectDeallocationTracker The GREYObjectDeallocationTracker instance that is being 29 | * deallocated. 30 | */ 31 | -(void)objectTrackerDidDeallocate:(GREYObjectDeallocationTracker *)objectDeallocationTracker; 32 | 33 | @end 34 | 35 | @interface GREYObjectDeallocationTracker : NSObject 36 | 37 | /** 38 | * Initialize the GREYObjectDeallocationTracker with a delegate object. 39 | * 40 | * @param object The object that should be tracked by the GREYObjectDeallocationTracker. 41 | * @param delegate The object that conforms to the GREYObjectDeallocationTrackerDelegate protocol 42 | * and wants to receive the delegate callback. 43 | */ 44 | - (instancetype)initWithObject:(id)object 45 | delegate:(id _Nullable)delegate; 46 | 47 | /** 48 | * @remark init is not an available initializer. Use the other initializer. 49 | */ 50 | - (instancetype)init NS_UNAVAILABLE; 51 | 52 | /** 53 | * Finds the GREYObjectDeallocationTracker associated with the @c object if one exists. Call this 54 | * method if the @c object is already being tracked by an instance of 55 | * GREYObjectDeallocationTracker. 56 | * 57 | * @param object The object that the GREYObjectDeallocationTracker is tracking. 58 | * 59 | * @return An instance of GREYObjectDeallocationTracker or nil if object's deallocation isn't 60 | * being tracked. 61 | */ 62 | + (GREYObjectDeallocationTracker * _Nullable)deallocationTrackerRegisteredWithObject:(id)object; 63 | 64 | @end 65 | 66 | NS_ASSUME_NONNULL_END 67 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYPickerAction.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * Actions for manipulating a UIPickerView. 23 | */ 24 | @interface GREYPickerAction : GREYBaseAction 25 | 26 | /** 27 | * @remark init is not an available initializer. Use the other initializers. 28 | */ 29 | - (instancetype)init NS_UNAVAILABLE; 30 | 31 | /** 32 | * @remark initWithName::constraints: is overridden from its superclass. 33 | */ 34 | - (instancetype)initWithName:(NSString *)name 35 | constraints:(id)constraints NS_UNAVAILABLE; 36 | 37 | /** 38 | * Selects a value in a given column of a UIPickerView. 39 | * 40 | * @param column Column of the UIPickerView to change. 41 | * @param value The value to set in the UIPickerView column. 42 | * 43 | * @return An instance of UIPickerAction, initialized with the @c column and @c value. 44 | */ 45 | - (instancetype)initWithColumn:(NSInteger)column value:(NSString *)value NS_DESIGNATED_INITIALIZER; 46 | 47 | @end 48 | 49 | NS_ASSUME_NONNULL_END 50 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYPinchAction.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | #import 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | /** 23 | * Error domain used for pinch related NSError objects. 24 | */ 25 | GREY_EXTERN NSString *const kGREYPinchErrorDomain; 26 | 27 | /** 28 | * Error codes for pinch related failures. 29 | */ 30 | typedef NS_ENUM(NSInteger, GREYPinchErrorCode) { 31 | kGREYPinchFailedErrorCode = 0, 32 | }; 33 | 34 | /** 35 | * A @c GREYAction that performs the pinch gesture on the view on which it is called. 36 | */ 37 | @interface GREYPinchAction : GREYBaseAction 38 | 39 | /** 40 | * Performs a pinch action in the given @c direction for the @c duration. The start of outward 41 | * pinch is from the center of the view and stops before 20% margin of the view's bounding rect. 42 | * 43 | * For an inward pinch the start point is at a 20% margin of the view's bounding rect on either 44 | * side and stops at the center. The default angle of the pinch action is 30 degrees to closely 45 | * match the average pinch angle of a natural right handed pinch. 46 | * 47 | * @param direction The direction of the pinch. 48 | * @param duration The time interval for which the pinch takes place. 49 | * @param pinchAngle Angle of the vector in radians to which the pinch direction is pointing. 50 | * 51 | * @returns An instance of @c GREYPinchAction, initialized with a provided direction and 52 | * duration and angle. 53 | */ 54 | - (instancetype)initWithDirection:(GREYPinchDirection)direction 55 | duration:(CFTimeInterval)duration 56 | pinchAngle:(double)pinchAngle; 57 | 58 | @end 59 | 60 | NS_ASSUME_NONNULL_END 61 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYScreenshotUtil+Internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | /** 18 | * @file GREYScreenshotUtil+Internal.h 19 | * @brief Exposes GREYScreenshotUtil' interfaces and methods that are otherwise private 20 | * for testing purposes. 21 | */ 22 | 23 | #import 24 | 25 | NS_ASSUME_NONNULL_BEGIN 26 | 27 | @interface GREYScreenshotUtil (Internal) 28 | 29 | /** 30 | * Provides a UIImage that is a screenshot, immediately or after the screen updates as specified. 31 | * 32 | * @param afterScreenUpdates A Boolean specifying if the screenshot is to be taken immediately or 33 | * after a screen update. 34 | * 35 | * @return A UIImage containing a screenshot. 36 | * 37 | * @remark This is available only for internal testing purposes. 38 | */ 39 | + (UIImage *)grey_takeScreenshotAfterScreenUpdates:(BOOL)afterScreenUpdates; 40 | 41 | @end 42 | 43 | NS_ASSUME_NONNULL_END 44 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYScrollToContentEdgeAction.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | #import 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | /** 23 | * A GREYAction that implements a scroll action that scrolls the contents of the matched 24 | * UIScrollView to the given edge of its contents. 25 | */ 26 | @interface GREYScrollToContentEdgeAction : GREYBaseAction 27 | 28 | /** 29 | * @remark init is not an available initializer. Use the other initializers. 30 | */ 31 | - (instancetype)init NS_UNAVAILABLE; 32 | 33 | /** 34 | * @remark initWithName::constraints: is overridden from its superclass. 35 | */ 36 | - (instancetype)initWithName:(NSString *)name 37 | constraints:(id)constraints NS_UNAVAILABLE; 38 | 39 | /** 40 | * Creates a scroll action that scrolls to the given @c edge of the contents in the selected 41 | * scroll view. 42 | * 43 | * @param edge The edge of the UIScrollView to scroll the contents. 44 | * 45 | * @return An instance of GREYScrollToContentEdgeAction, initialized with the provided @c edge. 46 | */ 47 | - (instancetype)initWithEdge:(GREYContentEdge)edge; 48 | 49 | /** 50 | * Creates a scroll action that scrolls to the given @c edge of the contents in the selected 51 | * scroll view with the start point specified by @c startPointPercents. 52 | * 53 | * @param edge The edge of the UIScrollView to scroll the contents. 54 | * @param startPointPercents The start point of the scroll specified as percents (0, 1) exclusive, 55 | * in the visible area of the scroll view or as @c NAN to pick a point 56 | * that provides maximum scroll length. 57 | * 58 | * @return An instance of GREYScrollToContentEdgeAction, initialized with the provided @c edge. 59 | */ 60 | - (instancetype)initWithEdge:(GREYContentEdge)edge 61 | startPointPercents:(CGPoint)startPointPercents NS_DESIGNATED_INITIALIZER; 62 | 63 | @end 64 | 65 | NS_ASSUME_NONNULL_END 66 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYSlideAction.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * A GREYAction that changes the value on a UISlider. 23 | */ 24 | @interface GREYSlideAction : GREYBaseAction 25 | 26 | /** 27 | * @remark init is not an available initializer. Use the other initializers. 28 | */ 29 | - (instancetype)init NS_UNAVAILABLE; 30 | 31 | /** 32 | * @remark initWithName::constraints: is overridden from its superclass. 33 | */ 34 | - (instancetype)initWithName:(NSString *)name 35 | constraints:(id)constraints NS_UNAVAILABLE; 36 | 37 | /** 38 | * Action for instances of UISlider that allow the thumb to be moved to a specific @c value. 39 | * 40 | * @param value Value to set on the Slider. 41 | * 42 | * @return An instance of GREYSlideAction, initialized with the provided slider value. 43 | */ 44 | - (instancetype)initWithSliderValue:(float)value NS_DESIGNATED_INITIALIZER; 45 | 46 | @end 47 | 48 | NS_ASSUME_NONNULL_END 49 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYStringDescription.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | #import 20 | 21 | /** 22 | * A string based implementation of GREYDescription protocol. 23 | */ 24 | @interface GREYStringDescription : NSObject 25 | @end 26 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYSurrogateDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * This class is used as a common base class for proxy delegates. 23 | * Primarily used to hold needed message forwarding methods. 24 | */ 25 | @interface GREYSurrogateDelegate : NSObject 26 | 27 | /** 28 | * @remark init is not an available initializer. Use the other initializers. 29 | */ 30 | - (instancetype)init NS_UNAVAILABLE; 31 | 32 | /** 33 | * Initializer that takes the original delegate and provides a surrogate backed by the original. 34 | * 35 | * @param originalDelegate The original delegate being proxied. This can be @c nil. 36 | * @param shouldBeWeak Specifies whether the delegate should be weak or strong. 37 | * 38 | * @return an instance of GREYSurrogateDelegate backed by the provided delegate. 39 | */ 40 | - (instancetype)initWithOriginalDelegate:(id)originalDelegate 41 | isWeak:(BOOL)shouldBeWeak NS_DESIGNATED_INITIALIZER; 42 | 43 | /** 44 | * @return The original delegate that's being proxied. 45 | */ 46 | - (id)originalDelegate; 47 | 48 | @end 49 | 50 | NS_ASSUME_NONNULL_END 51 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYTestCaseInvocation.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | /** 20 | * Class used for invoking a test case method and updating the status of the test case 21 | */ 22 | @interface GREYTestCaseInvocation : NSInvocation 23 | @end 24 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYTimedIdlingResource.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * An idling resource that changes to busy state for a specified amount of time. 23 | */ 24 | @interface GREYTimedIdlingResource : NSObject 25 | 26 | /** 27 | * An idling resouce for any @c object whose idleness is time-dependent. The resource reports 28 | * busy until @c seconds has elapsed. 29 | * 30 | * This idling resource self-registers with GREYUIThreadExecutor on creation and deregisters when 31 | * it idles or is forcefully stopped using GREYTimedIdlingResource::stopMonitoring. 32 | * 33 | * @param object The object to monitor. 34 | * @param seconds The amount of time after which object will be in idle state. 35 | * @param name A descriptive name for the idling resource. 36 | * 37 | * @return A new idling resource instance for @c object. 38 | */ 39 | + (instancetype)resourceForObject:(NSObject *)object 40 | thatIsBusyForDuration:(CFTimeInterval)seconds 41 | name:(NSString *)name; 42 | 43 | /** 44 | * @remark init is not an available initializer. Use the other initializers. 45 | */ 46 | - (instancetype)init NS_UNAVAILABLE; 47 | 48 | /** 49 | * Forcefully stops monitoring. 50 | * Subsequent invocations to GREYIdlingResource::isIdleNow return @c YES. 51 | */ 52 | - (void)stopMonitoring; 53 | 54 | @end 55 | 56 | NS_ASSUME_NONNULL_END 57 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYTraversal.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | #import 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | /** 23 | * A private wrapper used to store information that is essential for printing the UI hierarchy 24 | * appropriately and in correct order. 25 | */ 26 | @interface GREYTraversalObject : NSObject 27 | 28 | /** 29 | * An NSUInteger representing the number of parent-child relationships from the root element 30 | * to the current element. 31 | */ 32 | @property(nonatomic) NSUInteger level; 33 | 34 | /** 35 | * The UI element that the GREYHierarchyObject is wrapped around. 36 | */ 37 | @property(nonatomic, strong) id element; 38 | 39 | @end 40 | 41 | /** 42 | * Private class to traverse the UI Hierarchy. 43 | * Provides helper methods to access the various elements present in the hierarchy. 44 | */ 45 | @interface GREYTraversal : NSObject 46 | 47 | /** 48 | * Instance method that returns the next object from the hierarchy. Needs to be implemented by 49 | * subclasses. This class provides an empty implementation. 50 | * 51 | * @return An instance of the UI element that is next in the hierarchy. 52 | */ 53 | - (id _Nullable)nextObject NS_UNAVAILABLE; 54 | 55 | /** 56 | * Explores the immediate children of the @c element that is passed in. 57 | * 58 | * @param element The UI element whose children are to be explored. 59 | * 60 | * @return Creates a new array that contains the immediate children of @c element. The children are 61 | * ordered from front to back, meaning subviews that were added first are present later 62 | * in the array. If no children exist, then an empty array is returned. 63 | */ 64 | - (NSArray *)exploreImmediateChildren:(id)element; 65 | 66 | @end 67 | 68 | NS_ASSUME_NONNULL_END 69 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYTraversalBFS.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import "Traversal/GREYTraversal.h" 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | @interface GREYTraversalBFS : GREYTraversal 22 | 23 | /** 24 | * Instance method that returns the next object from the hierarchy in a Breadth First Search 25 | * fashion. 26 | * 27 | * @return An instance of the UI element that is next in the hierarchy. 28 | */ 29 | - (id _Nullable)nextObject; 30 | 31 | /** 32 | * Class method to initialize the object. The hierarchy is unrolled in a BFS fashion and 33 | * an internal representation is created. 34 | * 35 | * @param element Single UI element whose UI hierarchy is to be parsed. 36 | * 37 | * @return An instance of GREYTraversalBFS. 38 | */ 39 | + (instancetype)hierarchyForElementWithBFSTraversal:(id)element; 40 | 41 | /** 42 | * Enumerates through the entire hierarchy and calls the @c block on each element in the hierarchy. 43 | * This method enumerates through the hierarchy only once. 44 | * 45 | * @param block A completion block that will be invoked on each element. 46 | */ 47 | - (void)enumerateUsingBlock:(void (^)(id view, NSUInteger level))block; 48 | 49 | @end 50 | 51 | NS_ASSUME_NONNULL_END 52 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYTraversalDFS.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import "Traversal/GREYTraversal.h" 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | @interface GREYTraversalDFS : GREYTraversal 22 | 23 | /** 24 | * Instance method that returns the next object from the hierarchy in a Depth First Search fashion. 25 | * 26 | * @return An instance of the UI element that is next in the hierarchy. 27 | */ 28 | - (id _Nullable)nextObject; 29 | 30 | /** 31 | * Class method to initialize the object. The hierarchy is unrolled in a DFS fashion and 32 | * an internal representation is created. 33 | * 34 | * @param element Single UI element whose UI hierarchy needs to be unrolled. 35 | * 36 | * @return An instance of the GREYTraversalDFS class. 37 | */ 38 | + (instancetype)hierarchyForElementWithDFSTraversal:(id)element; 39 | 40 | /** 41 | * Enumerates through the entire hierarchy and calls the @c block on each element in the hierarchy. 42 | * This method enumerates through the hierarchy only once. 43 | * 44 | * @param block A completion block that will be invoked on each element. 45 | */ 46 | - (void)enumerateUsingBlock:(void (^)(id view, NSUInteger level))block; 47 | 48 | @end 49 | 50 | NS_ASSUME_NONNULL_END 51 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYUIThreadExecutor+Internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | /** 18 | * @file GREYUIThreadExecutor+Internal.h 19 | * @brief Exposes GREYUIThreadExecutor interfaces and methods that are otherwise private for 20 | * testing purposes. 21 | */ 22 | 23 | #import 24 | 25 | @protocol GREYIdlingResource; 26 | 27 | NS_ASSUME_NONNULL_BEGIN 28 | 29 | @interface GREYUIThreadExecutor (Internal) 30 | 31 | /** 32 | * Register the specified @c resource to be checked for idling before executing test actions. 33 | * A strong reference is held to @c resource until it is deregistered using 34 | * @c deregisterIdlingResource. It is safe to call this from any thread. 35 | * 36 | * @param resource The idling resource to register. 37 | * 38 | * @remark This is available only for internal testing purposes. 39 | */ 40 | - (void)registerIdlingResource:(id)resource; 41 | 42 | /** 43 | * Unregisters a previously registered @c resource. It is safe to call this from any thread. 44 | * 45 | * @param resource The resource to unregistered. 46 | * 47 | * @remark This is available only for internal testing purposes. 48 | */ 49 | - (void)deregisterIdlingResource:(id)resource; 50 | 51 | @end 52 | 53 | NS_ASSUME_NONNULL_END 54 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYUIWebViewDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | #if !defined(__IPHONE_12_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_12_0 20 | 21 | #import "Delegate/GREYSurrogateDelegate.h" 22 | 23 | NS_ASSUME_NONNULL_BEGIN 24 | 25 | /** 26 | * A UIWebView delegate proxy used to intercept load requests for syncing. 27 | */ 28 | @interface GREYUIWebViewDelegate : GREYSurrogateDelegate 29 | 30 | /** 31 | * @remark init is not an available initializer. Use the other initializers. 32 | */ 33 | - (instancetype)init NS_UNAVAILABLE; 34 | 35 | /** 36 | * Creates an instance of GREYUIWebViewDelegate backed by the provided delegate. 37 | * 38 | * @param originalDelegate The original delegate being proxied. 39 | * @return an instance of GREYUIWebViewDelegate backed by the original delegate. 40 | */ 41 | - (instancetype)initWithOriginalUIWebViewDelegate:(id)originalDelegate; 42 | 43 | @end 44 | 45 | NS_ASSUME_NONNULL_END 46 | 47 | #endif // !defined(__IPHONE_12_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_12_0 48 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/GREYUIWindowProvider.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * A provider for UIApplication windows. By default, all application windows are returned unless 23 | * this provider is initialized with custom windows. 24 | */ 25 | @interface GREYUIWindowProvider : NSObject 26 | 27 | /** 28 | * Class method to get a provider with the specified @c windows. 29 | * 30 | * @param windows An array of UIApplication windows to populate the provider. 31 | * 32 | * @return A GREYUIWindowProvider instance populated with the UIApplication windows in @c windows. 33 | */ 34 | + (instancetype)providerWithWindows:(NSArray *)windows; 35 | 36 | /** 37 | * Class method to get a provider with all the windows currently registered with the app. 38 | * 39 | * @return A GREYUIWindowProvider instance populated by all windows currently 40 | * registered with the app. 41 | */ 42 | + (instancetype)providerWithAllWindows; 43 | 44 | /** 45 | * @remark init is not an available initializer. Use the other initializers. 46 | */ 47 | - (instancetype)init NS_UNAVAILABLE; 48 | 49 | /** 50 | * Designated Initializer. 51 | * 52 | * @param windows UIApplication windows to populate the provider with. If @c windows is @c nil, it 53 | will initialize this provider with all windows currently registered with the 54 | app. Use initWithAllWindows constructor instead to make your intention explicit. 55 | * 56 | * @return A GREYUIWindowProvider instance, populated with the specified windows. 57 | */ 58 | - (instancetype)initWithWindows:(NSArray *_Nullable)windows NS_DESIGNATED_INITIALIZER; 59 | 60 | /** 61 | * Initializes this provider with all application windows. 62 | * 63 | * @return A GREYUIWindowProvider instance populated by all windows currently 64 | * registered with the app. 65 | */ 66 | - (instancetype)initWithAllWindows; 67 | 68 | /** 69 | * 70 | * @return A set of all application windows ordered by window-level from back to front. 71 | */ 72 | + (NSArray *)allWindows; 73 | 74 | #pragma mark - GREYProvider 75 | 76 | /** 77 | * 78 | * @return An enumerator for @c windows populating the window provider. 79 | */ 80 | - (NSEnumerator *)dataEnumerator; 81 | 82 | @end 83 | 84 | NS_ASSUME_NONNULL_END 85 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/NSError+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * Additions to NSError to facilitate error logging. 23 | */ 24 | @interface NSError (GREYAdditions) 25 | 26 | /** 27 | * For a given error, create a description dictionary of the error. 28 | * The description includes error's domain, error code and error description. 29 | * 30 | * @return A description dictionary for the given @c error. 31 | */ 32 | 33 | - (NSDictionary *)grey_descriptionDictionary; 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/NSRunLoop+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | /** 20 | * EarlGrey specific additions to NSRunLoop to track run loop timers. 21 | */ 22 | @interface NSRunLoop (GREYAdditions) 23 | @end 24 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/NSString+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * EarlGrey specific additions to NSString. 23 | */ 24 | @interface NSString (GREYAdditions) 25 | 26 | /** 27 | * Returns @c YES if the current string is @b not an empty string (length = 0) after being trimmed 28 | * for whitespaces and newline characters. 29 | * @remark Since it is valid to send this message to @c nil instances, we use @c isNonEmpty instead 30 | * of @c isEmpty to return a valid result (@c NO). 31 | * 32 | * @return @c NO if current string is empty, @c YES otherwise. 33 | */ 34 | - (BOOL)grey_isNonEmptyAfterTrimming; 35 | 36 | /** 37 | * @return A string with the MD5 hash of the given input @c string. 38 | */ 39 | - (NSString *)grey_md5String; 40 | 41 | @end 42 | 43 | NS_ASSUME_NONNULL_END 44 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/NSTimer+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | /** 20 | * EarlGrey specific additions to NSTimer to track timer events. 21 | */ 22 | @interface NSTimer (GREYAdditions) 23 | @end 24 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/NSURL+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | @interface NSURL (GREYAdditions) 22 | 23 | /** 24 | * Add @c regEx to the list of framework blacklisted URLs. 25 | * 26 | * @param regEx A regular expression representing a URL to blacklist from the tracking system. 27 | */ 28 | + (void)grey_addBlacklistRegEx:(NSString *)regEx; 29 | 30 | /** 31 | * @return @c YES if EarlGrey must synchronize with this url, @c NO otherwise. 32 | */ 33 | - (BOOL)grey_shouldSynchronize; 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/NSURLConnection+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * Additions to NSURLConnection to allow EarlGrey to track status for every connection. By 23 | * default, EarlGrey tracks all NSURLConnection's, to change this behavior update GREYConfiguration 24 | * setting with @c kGREYConfigKeyURLBlacklistRegex key. 25 | */ 26 | @interface NSURLConnection (GREYAdditions) 27 | 28 | /** 29 | * Tracks the current connection as pending in GREYAppStateTracker. 30 | */ 31 | - (void)grey_trackPending; 32 | 33 | /** 34 | * Untracks the current connection from GREYAppStateTracker, marking it as completed. 35 | */ 36 | - (void)grey_untrackPending; 37 | 38 | @end 39 | 40 | NS_ASSUME_NONNULL_END 41 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/NSURLSession+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | /** 20 | * Additions to NSURLSession to enable EarlGrey to synchronize with NSURLSessionTasks that execute 21 | * network requests. 22 | */ 23 | @interface NSURLSession (GREYAdditions) 24 | @end 25 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/UIAnimation+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | /** 20 | * EarlGrey additions for UIAnimation, UIKit's internal representation of animations used by some 21 | * of its components, such as UIScrollView. 22 | */ 23 | @interface UIAnimation_GREYAdditions : NSObject 24 | @end 25 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/UIApplication+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * EarlGrey specific additions for tracking runloop mode changes and user interaction events. 23 | */ 24 | @interface UIApplication (GREYAdditions) 25 | 26 | /** 27 | * @return Active mode for the main runloop that was pushed by one of the push runloop methods. 28 | * May return @c nil when no mode was pushed. 29 | */ 30 | - (NSString *_Nullable)grey_activeRunLoopMode; 31 | 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/UIGestureRecognizer+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | /** 20 | * Additions that allow EarlGrey to synchronize with UIGestureRecognizers. 21 | */ 22 | @interface UIGestureRecognizer (GREYAdditions) 23 | @end 24 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/UIScrollView+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * EarlGrey specific additions for tracking UIScrollView events (like scrolling, bouncing etc). 23 | */ 24 | @interface UIScrollView (GREYAdditions) 25 | 26 | /** 27 | * Returns @c YES if the scroll view is exerting resistance to scroll, since scroll views that do 28 | * not have bounce enabled cannot detect resistance unless some scroll is applied, the output of 29 | * this method only makes sense in the middle of a scroll action. 30 | * @remark This method has limited accuracy when used with scroll views having bounce disabled, 31 | * please see the implementation for more details. 32 | * 33 | * @return @c YES if the scroll view is exerting resistance to scroll, @c NO otherwise. 34 | */ 35 | - (BOOL)grey_hasScrollResistance; 36 | @end 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/UISwitch+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * Additions for the UISwitch class. 23 | */ 24 | @interface UISwitch (GREYAdditions) 25 | 26 | /** 27 | * @param onState The specified switch state. 28 | * 29 | * @return A string representation of the specified switch state. 30 | */ 31 | + (NSString *)grey_stringFromOnState:(BOOL)onState; 32 | 33 | @end 34 | 35 | NS_ASSUME_NONNULL_END 36 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/UITouch+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | @interface UITouch (GREYAdditions) 22 | 23 | /** 24 | * Creates a fake touch at @c point in window coordinates of the given @c window. 25 | * 26 | * @param point The location of this touch in window coordinates. 27 | * @param window The reference window used for coordinates passed as @c point. 28 | * 29 | * @return An initialized UITouch object 30 | */ 31 | - (id)initAtPoint:(CGPoint)point relativeToWindow:(UIWindow *)window; 32 | 33 | @end 34 | 35 | NS_ASSUME_NONNULL_END 36 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/UIView+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * EarlGrey specific additions for traversing and manipulating UIViews. 23 | */ 24 | @interface UIView (GREYAdditions) 25 | 26 | /** 27 | * @param klass The target class of subviews. 28 | * 29 | * @return A breadth-first / level ordered array of subviews that can be safely casted to @c klass. 30 | */ 31 | - (NSArray *)grey_childrenAssignableFromClass:(Class)klass; 32 | 33 | /** 34 | * Makes sure that subview @c view is always on top, even if other subviews are added in front of 35 | * it. Also keeps the @c view's frame fixed to the current value so parent can't change it. 36 | * 37 | * @param view The view to keep as the top-most fixed subview. 38 | */ 39 | - (void)grey_keepSubviewOnTopAndFrameFixed:(UIView *)view; 40 | 41 | /** 42 | * Makes this view and all its super view opaque. Successive calls to this method will replace 43 | * the previously stored alpha value, causing any saved value to be lost. 44 | * 45 | * @remark Each invocation will save the current alpha value which can be restored by calling 46 | * -[UIView grey_restoreOpacity] 47 | */ 48 | - (void)grey_recursivelyMakeOpaque; 49 | 50 | /** 51 | * Restores the opacity of this view and it's super views if they were made opaque by calling 52 | * -[UIView grey_recursivelyMakeOpaque]. If -[UIView grey_recursivelyMakeOpaque] was not 53 | * called before, then this method will perform a no-op on each of the view's superviews. 54 | */ 55 | - (void)grey_restoreOpacity; 56 | 57 | /** 58 | * Quick check to see if a view meets the basic criteria for visibility: 59 | * 1) Not hidden 60 | * 2) Visible with a minimum alpha 61 | * 3) Valid accessibility frame. 62 | * 63 | * Also checks to if a view is not a subview of another view or window that has a 64 | * translucent alpha value or is hidden. 65 | */ 66 | - (BOOL)grey_isVisible; 67 | 68 | @end 69 | 70 | NS_ASSUME_NONNULL_END 71 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/UIViewController+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | @interface UIViewController (GREYAdditions) 22 | 23 | /** 24 | * Tracks this view controller as the root view controller of @c window, setting up the desired 25 | * states so that EarlGrey can decide when to wait for this view controller to appear. This method 26 | * should be called each time window's @c hidden property changes. Passing @c nil for @c window 27 | * indicates this view controller is no longer a root view controller. 28 | * @todo Use KVO for the hidden property. 29 | * 30 | * @param window The window to which to associate this view controller as the root view controller. 31 | */ 32 | - (void)grey_trackAsRootViewControllerForWindow:(UIWindow *_Nullable)window; 33 | 34 | @end 35 | 36 | NS_ASSUME_NONNULL_END 37 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/UIWebView+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | #if !defined(__IPHONE_12_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_12_0 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | /** 24 | * Additions that allow EarlGrey to sync with UIWebView load requests. 25 | */ 26 | @interface UIWebView (GREYAdditions) 27 | 28 | /** 29 | * Explicitly clears the pending interaction state for UIWebViews. 30 | */ 31 | - (void)grey_clearPendingInteraction; 32 | 33 | /** 34 | * Will mark the UIWebView's state as busy waiting for interaction until @c seconds have elapsed or 35 | * UIWebView::grey_clearPendingInteraction is called (whichever comes first). 36 | * 37 | * @param seconds Time interval in seconds for which to mark the UIWebView as busy. 38 | */ 39 | - (void)grey_pendingInteractionForTime:(NSTimeInterval)seconds; 40 | 41 | /** 42 | * Marks webview as pending load in GREYAppStateTracker. 43 | */ 44 | - (void)grey_trackAJAXLoading; 45 | 46 | /** 47 | * Untracks webview loading state from GREYAppStateTracker. 48 | */ 49 | - (void)grey_untrackAJAXLoading; 50 | 51 | /** 52 | * Sets the loading state for this webview. 53 | * 54 | * @param loading BOOL value indicating the new loading state of this webview. 55 | */ 56 | - (void)grey_setIsLoadingFrame:(BOOL)loading; 57 | 58 | /** 59 | * @return the loading state for this webview. 60 | */ 61 | - (BOOL)grey_isLoadingFrame; 62 | 63 | @end 64 | 65 | NS_ASSUME_NONNULL_END 66 | 67 | #endif // !defined(__IPHONE_12_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_12_0 68 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/UIWindow+GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | @interface UIWindow (GREYAdditions) 20 | @end 21 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/_UIModalItemsPresentingViewController_GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | /** 20 | * Private iOS class that doesn't call through to @code [super viewWillDisappear:] @endcode. 21 | * Without this, EarlGrey is unable to synchronize with disappearance of views of this controller. 22 | * 23 | * @remark This is fixed in iOS 9. 24 | */ 25 | @interface _UIModalItemsPresentingViewController_GREYAdditions : NSObject 26 | @end 27 | -------------------------------------------------------------------------------- /TMDBTests/Frameworks/EarlGrey.framework/PrivateHeaders/__NSCFLocalDataTask_GREYAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Google Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * Additions to NSURLSessionTask to allow EarlGrey to track status for every network request. By 23 | * default EarlGrey tracks all URLs. To change this behavior, add blacklisted URL regex's to 24 | * @c GREYConfiguration with key @c kGREYConfigKeyURLBlacklistRegex. 25 | */ 26 | @interface __NSCFLocalDataTask_GREYAdditions : NSObject 27 | 28 | /** 29 | * Tracks the network task so that EarlGrey waits for its completion. 30 | */ 31 | - (void)grey_track; 32 | 33 | /** 34 | * Un-tracks the network task so that EarlGrey does not wait for it anymore. 35 | */ 36 | - (void)grey_untrack; 37 | 38 | /** 39 | * Marks the network task as an ignored request so that EarlGrey does not wait on it. 40 | */ 41 | - (void)grey_neverTrack; 42 | 43 | @end 44 | 45 | NS_ASSUME_NONNULL_END 46 | -------------------------------------------------------------------------------- /TMDBTests/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /TMDBTests/Mocks/URLProtocolMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TMDB 3 | // 4 | // Created by Maksym Shcheglov. 5 | // Copyright © 2021 Maksym Shcheglov. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | class URLProtocolMock: URLProtocol { 11 | static var requestHandler: ((URLRequest) throws -> (HTTPURLResponse, Data?))? 12 | 13 | override class func canInit(with request: URLRequest) -> Bool { 14 | return true 15 | } 16 | 17 | override class func canonicalRequest(for request: URLRequest) -> URLRequest { 18 | return request 19 | } 20 | 21 | override func startLoading() { 22 | guard let handler = URLProtocolMock.requestHandler else { 23 | assertionFailure("The handler is not provided!") 24 | return 25 | } 26 | 27 | do { 28 | let (response, data) = try handler(request) 29 | client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) 30 | if let data = data { 31 | client?.urlProtocol(self, didLoad: data) 32 | } 33 | client?.urlProtocolDidFinishLoading(self) 34 | } catch { 35 | client?.urlProtocol(self, didFailWithError: error) 36 | } 37 | } 38 | 39 | override func stopLoading() { 40 | // nop 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /TMDBTests/Responses/joker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgl0v/TMDB/5fc1aec6e6552f03d90809d0b672d490b8b7759a/TMDBTests/Responses/joker.jpg -------------------------------------------------------------------------------- /TMDBTests/UITests/MovieDetailsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovieDetailsTests.swift 3 | // TMDBTests 4 | // 5 | // Created by Maksym Shcheglov on 10/05/2020. 6 | // Copyright © 2020 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import EarlGrey 11 | import Combine 12 | @testable import TMDB 13 | 14 | class MovieDetailsTests: TMDBTestCase { 15 | 16 | private let movieId = 475557 17 | 18 | func test_showContent_whenDataIsLoaded() { 19 | // GIVEN 20 | let movieDetails = Movie.loadFromFile("MovieDetails.json") 21 | networkService.responses["/3/movie/\(movieId)"] = movieDetails 22 | 23 | // WHEN 24 | open(viewController: factory.movieDetailsController(movieId), flags: .embedInNavigation) 25 | 26 | // THEN 27 | Page.on(MovieDetailsPage.self) 28 | .assertTitle(movieDetails.title) 29 | .assertSubtitle(movieDetails.subtitle) 30 | .assertDescription(movieDetails.overview) 31 | } 32 | 33 | func test_showError_whenDataLoadingFailed() { 34 | // GIVEN / WHEN 35 | open(viewController: factory.movieDetailsController(movieId), flags: .embedInNavigation) 36 | 37 | 38 | // THEN 39 | Page.on(MovieDetailsPage.self) 40 | .assertContentIsHidden() 41 | .assertLoadingIndicatorIsHidden() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /TMDBTests/UITests/Pages/AlertPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlertPage.swift 3 | // TMDBTests 4 | // 5 | // Created by Maksym Shcheglov on 10/05/2020. 6 | // Copyright © 2020 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import EarlGrey 11 | 12 | class AlertPage: Page { 13 | 14 | override func verify() { 15 | assertVisible(AccessibilityIdentifiers.Alert.rootViewId) 16 | } 17 | 18 | @discardableResult 19 | func assertTitle(_ text: String) -> Self { 20 | return assertLabelText(AccessibilityIdentifiers.Alert.titleLabelId, text) 21 | } 22 | 23 | @discardableResult 24 | func assertDescription(_ text: String) -> Self { 25 | return assertLabelText(AccessibilityIdentifiers.Alert.descriptionLabelId, text) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /TMDBTests/UITests/Pages/MovieDetailsPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovieDetailsPage.swift 3 | // TMDBTests 4 | // 5 | // Created by Maksym Shcheglov on 10/05/2020. 6 | // Copyright © 2020 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import EarlGrey 11 | 12 | class MovieDetailsPage: Page { 13 | 14 | override func verify() { 15 | assertVisible(AccessibilityIdentifiers.MovieDetails.rootViewId) 16 | } 17 | } 18 | 19 | // MARK: Assertions 20 | extension MovieDetailsPage { 21 | 22 | @discardableResult 23 | func assertTitle(_ text: String) -> Self { 24 | return assertLabelText(AccessibilityIdentifiers.MovieDetails.titleLabelId, text) 25 | } 26 | 27 | @discardableResult 28 | func assertSubtitle(_ text: String) -> Self { 29 | return assertLabelText(AccessibilityIdentifiers.MovieDetails.subtitleLabelId, text) 30 | } 31 | 32 | @discardableResult 33 | func assertDescription(_ text: String) -> Self { 34 | return assertLabelText(AccessibilityIdentifiers.MovieDetails.descriptionLabelId, text) 35 | } 36 | 37 | @discardableResult 38 | func assertContentIsHidden() -> Self { 39 | return assertHidden(AccessibilityIdentifiers.MovieDetails.contentViewId) 40 | } 41 | 42 | @discardableResult 43 | func assertLoadingIndicatorIsVisible() -> Self { 44 | return assertVisible(AccessibilityIdentifiers.MovieDetails.loadingIndicatorId) 45 | } 46 | 47 | @discardableResult 48 | func assertLoadingIndicatorIsHidden() -> Self { 49 | return assertHidden(AccessibilityIdentifiers.MovieDetails.loadingIndicatorId) 50 | } 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /TMDBTests/UITests/Pages/MoviesSearchPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviesSearchPage.swift 3 | // TMDBTests 4 | // 5 | // Created by Maksym Shcheglov on 10/05/2020. 6 | // Copyright © 2020 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import EarlGrey 11 | 12 | class MoviesSearchPage: Page { 13 | 14 | override func verify() { 15 | assertExists(AccessibilityIdentifiers.MoviesSearch.rootViewId) 16 | } 17 | } 18 | 19 | // MARK: Actions 20 | extension MoviesSearchPage { 21 | 22 | @discardableResult 23 | func search(_ query: String) -> Self { 24 | EarlGrey 25 | .selectElement(with: grey_accessibilityID(AccessibilityIdentifiers.MoviesSearch.searchTextFieldId)) 26 | .perform(grey_typeText(query)) 27 | return dismissKeyboard() 28 | } 29 | 30 | @discardableResult 31 | func tapCell(at index: Int) -> Self { 32 | return performTap(withId: "\(AccessibilityIdentifiers.MoviesSearch.cellId).\(index)") 33 | } 34 | } 35 | 36 | // MARK: Assertions 37 | extension MoviesSearchPage { 38 | 39 | @discardableResult 40 | func assertScreenTitle(_ text: String) -> Self { 41 | EarlGrey.selectElement(with: grey_text(text)).assert(grey_sufficientlyVisible()) 42 | return self 43 | } 44 | 45 | @discardableResult 46 | func assertContentIsHidden() -> Self { 47 | return assertHidden(AccessibilityIdentifiers.MoviesSearch.tableViewId) 48 | } 49 | 50 | @discardableResult 51 | func assertMoviesCount(_ rowsCount: Int) -> Self { 52 | EarlGrey.selectElement(with: grey_accessibilityID(AccessibilityIdentifiers.MoviesSearch.tableViewId)) 53 | .assert(createTableViewRowsAssert(rowsCount: rowsCount, inSection: 0)) 54 | return self 55 | } 56 | 57 | private func createTableViewRowsAssert(rowsCount: Int, inSection section: Int) -> GREYAssertion { 58 | return GREYAssertionBlock(name: "TableViewRowsAssert") { (element, error) -> Bool in 59 | guard let tableView = element as? UITableView, tableView.numberOfSections > section else { 60 | return false 61 | } 62 | let numberOfCells = tableView.numberOfRows(inSection: section) 63 | return numberOfCells == rowsCount 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /TMDBTests/UITests/Utils/FakeAppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FakeAppDelegate.swift 3 | // TMDBTests 4 | // 5 | // Created by Maksym Shcheglov on 08/05/2020. 6 | // Copyright © 2020 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FakeAppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | window = UIWindow(frame: UIScreen.main.bounds) 17 | window?.rootViewController = UIViewController() 18 | window?.makeKeyAndVisible() 19 | return true 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /TMDBTests/UITests/Utils/TMDBTestCase.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestCase+Utils.swift 3 | // TMDBTests 4 | // 5 | // Created by Maksym Shcheglov on 10/05/2020. 6 | // Copyright © 2020 Maksym Shcheglov. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import EarlGrey 11 | @testable import TMDB 12 | 13 | class TMDBTestCase: XCTestCase { 14 | 15 | lazy var factory = ApplicationComponentsFactory(servicesProvider: ServicesProvider(network: networkService, imageLoader: imageLoader)) 16 | lazy var networkService = NetworkServiceTypeMock() 17 | lazy var imageLoader: ImageLoaderServiceType = { 18 | let mock = ImageLoaderServiceTypeMock() 19 | mock.loadImageFromClosure = { _ in 20 | let image = UIImage(named: "joker.jpg", in: Bundle(for: EarlGrey.self), compatibleWith: nil) 21 | return .just(image) 22 | } 23 | return mock 24 | }() 25 | 26 | override func setUp() { 27 | setupEarlGrey() 28 | } 29 | 30 | private func setupEarlGrey() { 31 | GREYConfiguration.sharedInstance().setValue(false, forConfigKey: kGREYConfigKeyAnalyticsEnabled) // Disable Google analytics tracking 32 | GREYConfiguration.sharedInstance().setValue(5.0, forConfigKey: kGREYConfigKeyInteractionTimeoutDuration) // use 5s timeout for any interaction 33 | GREYTestHelper.enableFastAnimation() // increase the speed of your tests by not having to wait on slow animations. 34 | } 35 | 36 | struct OpenViewControllerFlags: OptionSet { 37 | let rawValue: Int 38 | 39 | static let presentModally = OpenViewControllerFlags(rawValue: 1 << 0) 40 | static let embedInNavigation = OpenViewControllerFlags(rawValue: 1 << 1) 41 | static let all: OpenViewControllerFlags = [.presentModally, .embedInNavigation] 42 | } 43 | 44 | func open(viewController: UIViewController, flags: OpenViewControllerFlags = .presentModally) { 45 | let viewControllerToOpen = flags.contains(.embedInNavigation) ? UINavigationController(rootViewController: viewController) : viewController 46 | viewControllerToOpen.modalPresentationStyle = .fullScreen 47 | let window = (UIApplication.shared.delegate as! FakeAppDelegate).window! 48 | 49 | if flags.contains(.presentModally) { 50 | window.rootViewController = UIViewController() 51 | window.rootViewController?.present(viewControllerToOpen, animated: false, completion: nil) 52 | } else { 53 | window.rootViewController = viewControllerToOpen 54 | } 55 | } 56 | } 57 | 58 | extension Decodable { 59 | static func loadFromFile(_ filename: String) -> Self { 60 | do { 61 | let path = Bundle(for: EarlGrey.self).path(forResource: filename, ofType: nil)! 62 | let data = try Data(contentsOf: URL(fileURLWithPath: path)) 63 | return try JSONDecoder().decode(Self.self, from: data) 64 | } catch { 65 | fatalError("Error: \(error)") 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /TMDBTests/UnitTests/ApplicationFlowCoordinatorTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TMDB 3 | // 4 | // Created by Maksym Shcheglov. 5 | // Copyright © 2021 Maksym Shcheglov. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | import XCTest 10 | @testable import TMDB 11 | 12 | class ApplicationFlowCoordinatorTests: XCTestCase { 13 | 14 | private lazy var flowCoordinator = ApplicationFlowCoordinator(window: window, dependencyProvider: dependencyProvider) 15 | private let window = UIWindow() 16 | private let dependencyProvider = ApplicationFlowCoordinatorDependencyProviderMock() 17 | 18 | /// Test that application flow is started correctly 19 | func test_startsApplicationsFlow() { 20 | // GIVEN 21 | let rootViewController = UINavigationController() 22 | dependencyProvider.moviesSearchNavigationControllerReturnValue = rootViewController 23 | 24 | // WHEN 25 | flowCoordinator.start() 26 | 27 | // THEN 28 | XCTAssertEqual(window.rootViewController, rootViewController) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /TMDBTests/UnitTests/MoviesSearchViewModelTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TMDB 3 | // 4 | // Created by Maksym Shcheglov. 5 | // Copyright © 2021 Maksym Shcheglov. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | import XCTest 10 | import Combine 11 | @testable import TMDB 12 | 13 | class MoviesSearchViewModelTests: XCTestCase { 14 | private let useCase = MoviesUseCaseTypeMock() 15 | private let navigator = MoviesSearchNavigatorMock() 16 | private var viewModel: MoviesSearchViewModel! 17 | private var cancellables: [AnyCancellable] = [] 18 | 19 | override func setUp() { 20 | viewModel = MoviesSearchViewModel(useCase: useCase, navigator: navigator) 21 | } 22 | 23 | func test_loadData_onSearch() { 24 | // Given 25 | let search = PassthroughSubject() 26 | let input = MoviesSearchViewModelInput(appear: .just(()), search: search.eraseToAnyPublisher(), selection: .empty()) 27 | var state: MoviesSearchState? 28 | 29 | let expectation = self.expectation(description: "movies") 30 | let movies = Movies.loadFromFile("Movies.json") 31 | let expectedViewModels = movies.items.map({ movie in 32 | return MovieViewModelBuilder.viewModel(from: movie, imageLoader: { _ in .just(UIImage()) }) 33 | }) 34 | useCase.searchMoviesWithReturnValue = .just(.success(movies)) 35 | useCase.loadImageForSizeReturnValue = .just(UIImage()) 36 | viewModel.transform(input: input).sink { value in 37 | guard case MoviesSearchState.success = value else { return } 38 | state = value 39 | expectation.fulfill() 40 | }.store(in: &cancellables) 41 | 42 | // When 43 | search.send("joker") 44 | 45 | // Then 46 | waitForExpectations(timeout: 1.0, handler: nil) 47 | XCTAssertEqual(state!, .success(expectedViewModels)) 48 | } 49 | 50 | func test_hasErrorState_whenDataLoadingIsFailed() { 51 | // Given 52 | let search = PassthroughSubject() 53 | let input = MoviesSearchViewModelInput(appear: .just(()), search: search.eraseToAnyPublisher(), selection: .empty()) 54 | var state: MoviesSearchState? 55 | 56 | let expectation = self.expectation(description: "movies") 57 | useCase.searchMoviesWithReturnValue = .just(.failure(NetworkError.invalidResponse)) 58 | useCase.loadImageForSizeReturnValue = .just(UIImage()) 59 | viewModel.transform(input: input).sink { value in 60 | guard case .failure = value else { return } 61 | state = value 62 | expectation.fulfill() 63 | }.store(in: &cancellables) 64 | 65 | // When 66 | search.send("joker") 67 | 68 | // Then 69 | waitForExpectations(timeout: 1.0, handler: nil) 70 | XCTAssertEqual(state!, .failure(NetworkError.invalidResponse)) 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /TMDBTests/UnitTests/MoviesUseCaseTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TMDB 3 | // 4 | // Created by Maksym Shcheglov. 5 | // Copyright © 2021 Maksym Shcheglov. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | import XCTest 10 | import Combine 11 | @testable import TMDB 12 | 13 | class MoviesUseCaseTests: XCTestCase { 14 | 15 | private let networkService = NetworkServiceTypeMock() 16 | private let imageLoaderService = ImageLoaderServiceTypeMock() 17 | private var useCase: MoviesUseCase! 18 | private var cancellables: [AnyCancellable] = [] 19 | 20 | override func setUp() { 21 | useCase = MoviesUseCase(networkService: networkService, 22 | imageLoaderService: imageLoaderService) 23 | } 24 | 25 | func test_searchMoviesSucceeds() { 26 | // Given 27 | var result: Result! 28 | let expectation = self.expectation(description: "movies") 29 | let movies = Movies.loadFromFile("Movies.json") 30 | networkService.responses["/3/search/movie"] = movies 31 | 32 | // When 33 | useCase.searchMovies(with: "joker").sink { value in 34 | result = value 35 | expectation.fulfill() 36 | }.store(in: &cancellables) 37 | 38 | // Then 39 | self.waitForExpectations(timeout: 1.0, handler: nil) 40 | guard case .success = result! else { 41 | XCTFail() 42 | return 43 | } 44 | } 45 | 46 | func test_searchMoviesFailes_onNetworkError() { 47 | // Given 48 | var result: Result! 49 | let expectation = self.expectation(description: "movies") 50 | networkService.responses["/3/search/movie"] = NetworkError.invalidResponse 51 | 52 | // When 53 | useCase.searchMovies(with: "joker").sink { value in 54 | result = value 55 | expectation.fulfill() 56 | }.store(in: &cancellables) 57 | 58 | // Then 59 | self.waitForExpectations(timeout: 1.0, handler: nil) 60 | guard case .failure = result! else { 61 | XCTFail() 62 | return 63 | } 64 | } 65 | 66 | func test_loadsImageFromNetwork() { 67 | // Given 68 | let movies = Movies.loadFromFile("Movies.json") 69 | let movie = movies.items.first! 70 | var result: UIImage? 71 | let expectation = self.expectation(description: "loadImage") 72 | imageLoaderService.loadImageFromReturnValue = .just(UIImage()) 73 | 74 | // When 75 | useCase.loadImage(for: movie, size: .small).sink { value in 76 | result = value 77 | expectation.fulfill() 78 | }.store(in: &cancellables) 79 | 80 | // Then 81 | self.waitForExpectations(timeout: 1.0, handler: nil) 82 | XCTAssertNotNil(result) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /screenshots/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgl0v/TMDB/5fc1aec6e6552f03d90809d0b672d490b8b7759a/screenshots/demo.gif --------------------------------------------------------------------------------