Skip to content

Commit

Permalink
docs + chaining actions
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan Aguele and Ondrej Rafaj committed Nov 6, 2017
1 parent f670bb4 commit 80f0d61
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 17 deletions.
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion SpecTools/Classes/Action/Action+Button.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

}
9 changes: 6 additions & 3 deletions SpecTools/Classes/Action/Action+ScrollView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}

}
3 changes: 2 additions & 1 deletion SpecTools/Classes/Action/Action+UICollectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

}
7 changes: 4 additions & 3 deletions SpecTools/Classes/Action/Action+UIGestureRecognizer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand All @@ -31,9 +31,9 @@ public typealias TargetActionInfo = [(target: AnyObject, action: Selector)]
recognizer.spec.action.execute()
}
}
return self
}


}


Expand Down Expand Up @@ -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
}

}
Expand Down
3 changes: 2 additions & 1 deletion SpecTools/Classes/Action/Action+UITableView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

}
16 changes: 10 additions & 6 deletions SpecTools/Classes/Prepare/Prepare+UIViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(ofClass classType: T.Type? = nil) where T: UINavigationController {
@discardableResult public func assignNavigationController<T>(ofClass classType: T.Type? = nil) -> Prepare where T: UINavigationController {
var nc: UINavigationController
if classType == nil {
nc = UINavigationController(rootViewController: element)
Expand All @@ -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
}

}
Expand Down

0 comments on commit 80f0d61

Please sign in to comment.