diff --git a/README.md b/README.md index c568628..7e48e13 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Library that helps you write less code when testing interface in your iOS apps. ## Implementation -After you add SpecTools framework a set of options will become available for most of the UI elements through a spec property. +After you add SpecTools framework a set of options will become available for most of the UI elements through a spec property. Available for iOS and tvOS These are: * action @@ -181,7 +181,7 @@ collectionView.spec.action.tap(item: 3) collectionView.spec.action.tap(item: 2, section: 1) ``` -#### Executing gesture recognizers +#### Executing gesture recognizers (not available on tvOS) Execute action on any UIGestureRecognizer ```Swift @@ -194,6 +194,25 @@ Get array of targets from any UIGestureRecognizer recognizer.spec.action.getTargetInfo() ``` +#### Simulating scrolls + +Simulate scrolling on any UIScrollView (or table/collection view) while calling all available delegate methods in the right order along the way + - decelerate sets if the scroll view should simulate decelerating after dragging +```Swift +scrollView.spec.action.scroll(to: CGPoint(x: 500, y: 0), decelerate: true) +``` +------ +Simulate scrolling on any UIScrollView to a specific horizontal page +```Swift +scrollView.spec.action.scroll(horizontalPageIndex: 2, decelerate: false) +``` +------ +Simulate scrolling on any UIScrollView to a specific vertical page +```Swift +scrollView.spec.action.scroll(verticalPageIndex: 5, decelerate: true) +``` +------ + ### Checks #### Checking view visibility diff --git a/SpecTools/Classes/Action/Action+Button.swift b/SpecTools/Classes/Action/Action+Button.swift index f7da89e..5cd7bf8 100644 --- a/SpecTools/Classes/Action/Action+Button.swift +++ b/SpecTools/Classes/Action/Action+Button.swift @@ -16,8 +16,9 @@ extension Action where T: UIButton { /// Simulate tap on a button /// - Parameter event: Event type to trigger - public func tap(event: UIControlEvents = .touchUpInside) { + @discardableResult public func tap(event: UIControlEvents = .touchUpInside) -> Action { element.sendActions(for: event) + return self } } diff --git a/SpecTools/Classes/Action/Action+ScrollView.swift b/SpecTools/Classes/Action/Action+ScrollView.swift index b429210..9af2423 100644 --- a/SpecTools/Classes/Action/Action+ScrollView.swift +++ b/SpecTools/Classes/Action/Action+ScrollView.swift @@ -16,7 +16,7 @@ extension Action where T: UIScrollView { /// Simulate scroll to a given point /// - Parameter to: Target offset value /// - Parameter decelerate: Enables deceleration after dragging - public func scroll(to point: CGPoint, decelerate: Bool = false) { + @discardableResult public func scroll(to point: CGPoint, decelerate: Bool = false) -> Action { element.delegate?.scrollViewWillBeginDragging?(element) element.contentOffset = point @@ -32,22 +32,25 @@ extension Action where T: UIScrollView { element.delegate?.scrollViewWillBeginDecelerating?(element) element.delegate?.scrollViewDidEndDecelerating?(element) } + return self } /// Simulate scroll to a given page horizontally /// - Parameter to: Target page index /// - Parameter decelerate: Enables deceleration after dragging - public func scroll(horizontalPageIndex index: Int, decelerate: Bool = false) { + @discardableResult public func scroll(horizontalPageIndex index: Int, decelerate: Bool = false) -> Action { let x = CGFloat(index) * element.frame.width scroll(to: CGPoint(x: x, y: element.contentOffset.y)) + return self } /// Simulate scroll to a given page vertically /// - Parameter to: Target page index /// - Parameter decelerate: Enables deceleration after dragging - public func scroll(verticalPageIndex index: Int, decelerate: Bool = false) { + @discardableResult public func scroll(verticalPageIndex index: Int, decelerate: Bool = false) -> Action { let y = CGFloat(index) * element.frame.height scroll(to: CGPoint(x: element.contentOffset.x, y: y)) + return self } } diff --git a/SpecTools/Classes/Action/Action+UICollectionView.swift b/SpecTools/Classes/Action/Action+UICollectionView.swift index 053d3a6..e7d6bb5 100644 --- a/SpecTools/Classes/Action/Action+UICollectionView.swift +++ b/SpecTools/Classes/Action/Action+UICollectionView.swift @@ -16,8 +16,9 @@ extension Action where T: UICollectionView { /// Simulate tap on a cell in collection view /// - Parameter item: Index of an item to tap on /// - Parameter section: Index of the section to tap on - public func tap(item: Int, section: Int = 0) { + @discardableResult public func tap(item: Int, section: Int = 0) -> Action { element.delegate?.collectionView?(element, didSelectItemAt: IndexPath(item: item, section: section)) + return self } } diff --git a/SpecTools/Classes/Action/Action+UIGestureRecognizer.swift b/SpecTools/Classes/Action/Action+UIGestureRecognizer.swift index ade304b..6d6f305 100644 --- a/SpecTools/Classes/Action/Action+UIGestureRecognizer.swift +++ b/SpecTools/Classes/Action/Action+UIGestureRecognizer.swift @@ -21,7 +21,7 @@ public typealias TargetActionInfo = [(target: AnyObject, action: Selector)] /// Simulate tap on a gesture recognizer /// - Parameter taps: Number of taps /// - Parameter touches: Number of touches - public func triggerTap(taps: Int = 1, touches: Int = 1) { + @discardableResult public func triggerTap(taps: Int = 1, touches: Int = 1) -> Action { if element.isUserInteractionEnabled == false { fatalError("User interactions are disabled. Gesture recognizer can't be used") } @@ -31,9 +31,9 @@ public typealias TargetActionInfo = [(target: AnyObject, action: Selector)] recognizer.spec.action.execute() } } + return self } - } @@ -66,11 +66,12 @@ public typealias TargetActionInfo = [(target: AnyObject, action: Selector)] } /// Executes all targets on a specific gesture recognizer - public func execute() { + @discardableResult public func execute() -> Action { let targetsInfo = element.spec.action.getTargetInfo() for info in targetsInfo { info.target.performSelector(onMainThread: info.action, with: nil, waitUntilDone: true) } + return self } } diff --git a/SpecTools/Classes/Action/Action+UITableView.swift b/SpecTools/Classes/Action/Action+UITableView.swift index 1eb1b71..d419c9a 100644 --- a/SpecTools/Classes/Action/Action+UITableView.swift +++ b/SpecTools/Classes/Action/Action+UITableView.swift @@ -16,8 +16,9 @@ extension Action where T: UITableView { /// Simulate tap on a cell in table view /// - Parameter row: Index of the row to tap on /// - Parameter section: Index of the section to tap on - public func tap(row: Int, section: Int = 0) { + @discardableResult public func tap(row: Int, section: Int = 0) -> Action { element.delegate?.tableView?(element, didSelectRowAt: IndexPath(row: row, section: section)) + return self } } diff --git a/SpecTools/Classes/Prepare/Prepare+UIViewController.swift b/SpecTools/Classes/Prepare/Prepare+UIViewController.swift index 074c2c3..0c8eb43 100644 --- a/SpecTools/Classes/Prepare/Prepare+UIViewController.swift +++ b/SpecTools/Classes/Prepare/Prepare+UIViewController.swift @@ -49,30 +49,33 @@ extension Prepare where T: UIViewController { // MARK: Preparation methods for UIViewController /// Will touch view of a view controller in order to get loadView and viewDidLoad called, than manually calls viewWillAppear and viewDidAppear with animations disabled - public func simulatePresentViewController() { + @discardableResult public func simulatePresentViewController() -> Prepare { element.loadViewIfNeeded() element.viewWillAppear(false) element.viewDidAppear(false) + return self } /// Set a new size for a view controllers view during runtime - public func set(viewSize: CGSize) { + @discardableResult public func set(viewSize: CGSize) -> Prepare { element.view.frame.size = viewSize element.view.setNeedsLayout() element.view.layoutIfNeeded() + return self } /// Set a screensize of a desired device on a view of your view controller, you can specify a custom height. Custom height might be useful when scrollviews are present - public func set(viewSize: DeviceScreenSize, height: CGFloat? = nil) { + @discardableResult public func set(viewSize: DeviceScreenSize, height: CGFloat? = nil) -> Prepare { var size = DeviceScreenSize.size(for: viewSize) if height != nil && height! >= 0 { size.height = height! } set(viewSize: size) + return self } /// Give view controller a navigation controller - public func assignNavigationController(ofClass classType: T.Type? = nil) where T: UINavigationController { + @discardableResult public func assignNavigationController(ofClass classType: T.Type? = nil) -> Prepare where T: UINavigationController { var nc: UINavigationController if classType == nil { nc = UINavigationController(rootViewController: element) @@ -81,13 +84,14 @@ extension Prepare where T: UIViewController { nc = classType!.init(rootViewController: element) } nc.spec.prepare.simulatePresentViewController() + return self } /// Give view controller a mock navigation controller which mainly allows for testing push/pop functionality - public func assignMockNavigationController() -> MockNavigationController { + @discardableResult public func assignMockNavigationController() -> Prepare { let nc = MockNavigationController(rootViewController: element) nc.spec.prepare.simulatePresentViewController() - return nc + return self } }