Reputation: 2251
In my one of UITableView
have more then 10 rows. I want to scroll till last row while UITestCase
running.
I have written below code to scroll till last row.
-(void)scrollToElement:(XCUIElement *)element application:(XCUIApplication *)app{
while ([self visible:element withApplication:app]) {
XCUIElement *searchResultTableView = app.tables[@"searchResultView"];
XCUICoordinate *startCoord = [searchResultTableView coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)];
XCUICoordinate *endCoord = [startCoord coordinateWithOffset:CGVectorMake(0.0, -262)];
[startCoord pressForDuration:0.01 thenDragToCoordinate:endCoord];
}
}
-(BOOL)visible:(XCUIElement *)element withApplication:(XCUIApplication *)app{
if (element.exists && !CGRectIsEmpty(element.frame) && element.isHittable) {
return CGRectContainsRect([app.windows elementBoundByIndex:0].frame, element.frame);
} else {
return FALSE;
}
}
An i have called above method in my one of UITestCase
method by below code
XCUIElement *searchResultTableView = app.tables[@"searchResultView"];
[self waitForElementToAppear:searchResultTableView withTimeout:30];
XCUIElement *table = [app.tables elementBoundByIndex:0];
XCUIElement *lastCell = [table.cells elementBoundByIndex:table.cells.count - 1];
[self scrollToElement:lastCell application:app];
By this code i can scroll to last row but after reaching last row, it continue doing scroll means can't stop scrolling.
Please help me to scroll to only last row and then it should stop to scroll so that i can perform next action event.
I have refer StackOverFlow
answer but none of them meet my requirement.
Thanks in advance.
Upvotes: 5
Views: 1751
Reputation: 982
I faced similar issue in one of my project. In that I wanted to test "Load More" feature by TestKit framework.
Here is some workaround to achieve the same scenario.
//app : is your current instance of appliaction
//listTable : is a Table which you've found via accessibility identifier
//loadMoreTest : is a parameter to determine whether code should perform test for loadmore feature or not
- (void)testScrollableTableForApplication:(XCUIApplication *)app
forTable:(XCUIElement *)listTable
withLoadMoreTest:(BOOL)loadMoreTest {
[listTable accessibilityScroll:UIAccessibilityScrollDirectionUp];
[listTable swipeUp];
if (loadMoreTest) {
__block BOOL isLoadMoreCalled;
__block XCUIElement *lastCell;
__block __weak void (^load_more)();
void (^loadMoreCall)();
load_more = loadMoreCall = ^() {
XCUIElementQuery *tablesQuery = app.tables;
XCUIElementQuery *cellQuery = [tablesQuery.cells containingType:XCUIElementTypeCell identifier:@"LoadMoreCell"];
lastCell = cellQuery.element;
if ([lastCell elementIsWithinWindowForApplication:app]) {
[self waitForElementToAppear:lastCell withTimeout:2];
[lastCell tap];
isLoadMoreCalled = true;
[self wait:2];
}
[listTable swipeUp];
if (!isLoadMoreCalled) {
load_more();
}
};
loadMoreCall();
}
}
- (void)waitForElementToAppear:(XCUIElement *)element withTimeout:(NSTimeInterval)timeout
{
NSUInteger line = __LINE__;
NSString *file = [NSString stringWithUTF8String:__FILE__];
NSPredicate *existsPredicate = [NSPredicate predicateWithFormat:@"exists == 1"];
[self expectationForPredicate:existsPredicate evaluatedWithObject:element handler:nil];
[self waitForExpectationsWithTimeout:timeout handler:^(NSError * _Nullable error) {
if (error != nil) {
NSString *message = [NSString stringWithFormat:@"Failed to find %@ after %f seconds",element,timeout];
[self recordFailureWithDescription:message inFile:file atLine:line expected:YES];
}
}];
}
create one category for XCUIElement XCUIElement+Helper.m and import it into your respective Test class.
#import <XCTest/XCTest.h>
@interface XCUIElement (Helper)
/// Check whether current XCUIElement is within current window or not
- (BOOL)elementIsWithinWindowForApplication:(XCUIApplication *)app ;
@end
@implementation XCUIElement (Helper)
/// Check whether current XCUIElement is within current window or not
/*
@description: we need to check particular element's frame and window's frame is intersecting or not, to get perfectly outcome whether element is currently visible on screen or not, because if element has not yet appeared on screen then also the flag frame, exists and hittable can become true
*/
- (BOOL)elementIsWithinWindowForApplication:(XCUIApplication *)app {
if (self.exists && !CGRectIsEmpty(self.frame) && self.hittable)
return CGRectContainsRect(app.windows.allElementsBoundByIndex[0].frame, self.frame);
else
return false;
}
@end
To get the "Load More" cell, i've given the
cell.accessibilityIdentifier = @"LoadMoreCell";
Rest of the code is, recursive function in testScrollableTableForApplication to make Tableview scroll to reach to bottom so i can have the access of load more cell(in your case last cell). Then i am performing the action Tap to fetch new records from server. Then again i am scrolling the Table to verify if the new records has been fetched from server or not.
Tip : you can replace recursive function with do while or while loop to achieve the same.
Hope this helps!
Happy Coding!!
Upvotes: 8