Reputation: 8719
I have implemented leading and trailing swipe actions in a table view. Now, I'm trying to test them in XCTest UI tests.
To test a regular swipe in either direction is easy:
tableCell.swipeRight()
tableCell.swipeLeft()
Using one of these causes the 1st action button to be displayed, and I can then .tap()
on the button.
However, testing a full swipe is proving a little more challenging. I have played with this extension from How do I swipe faster or more precisely?
I have also played with this answer from the question Xcode7 ui testing: staticTexts[“XX”].swipeRight() swipes not far enough.
Both of these essentially use XCUIElement's coordinate(withNormalizedOffset:) method to swipe from one point to another, similar to the following:
let startPoint = tableCell.coordinate(withNormalizedOffset: CGVector.zero)
let finishPoint = startPoint.withOffset(CGVector(dx:xOffsetValue, dy:yOffsetValue))
startPoint.press(forDuration: 0, thenDragTo: finishPoint)
I ended up with an extension that successfully performs a full swipe right - but I can't seem to get the numbers right for a full swipe left.
My code does perform a swipe left, but just doesn't go far enough. I've tried hardcoded numbers for dx:
from -300 to 300. The element width is 414. I believe that 0 is the far left, and 414 would be the far right, so I started using that size as a reference. Still, no joy.
How can I get this to perform a full swipe left?
extension XCUIElement
{
enum SwipeDirection {
case left, right
}
func longSwipe(_ direction : SwipeDirection) {
let elementLength = self.frame.size.width
let centerPoint: CGFloat = elementLength / 2.0
let halfCenterValue: CGFloat = centerPoint / 2.0
let startOffset: CGVector
let endOffset: CGVector
switch direction {
case .right: // this one works perfectly!
startOffset = CGVector.zero
endOffset = CGVector(dx: centerPoint + halfCenterValue, dy: 0)
}
case .left: // "There's the rub" as Hamlet might say...
startOffset = CGVector(dx: centerPoint + halfCenterValue, dy: 0)
endOffset = CGVector.zero
let startPoint = self.coordinate(withNormalizedOffset: startOffset)
let finishPoint = startPoint.withOffset(endOffset)
startPoint.press(forDuration: 0, thenDragTo: finishPoint)
}
}
Upvotes: 3
Views: 2731
Reputation: 8719
Got it!
First, I didn't need to use the frame size of the cell. The "normalized" part means that you can use values from 0.0 to 1.0 to represent a percentage of an element's size.
Second, playing with the sizes, I found a long swipe needs to move about 60% of the width of the cell in order to activate the action.
My resulting long swipe extension:
extension XCUIElement
{
enum SwipeDirection {
case left, right
}
func longSwipe(_ direction : SwipeDirection) {
let startOffset: CGVector
let endOffset: CGVector
switch direction {
case .right:
startOffset = CGVector.zero
endOffset = CGVector(dx: 0.6, dy: 0.0)
case .left:
startOffset = CGVector(dx: 0.6, dy: 0.0)
endOffset = CGVector.zero
}
let startPoint = self.coordinate(withNormalizedOffset: startOffset)
let endPoint = self.coordinate(withNormalizedOffset: endOffset)
startPoint.press(forDuration: 0, thenDragTo: endPoint)
}
}
Note: CGVector.zero
is a Swift alias for CGVector(dx: 0.0, dy: 0.0)
Upvotes: 5