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.
For example, many developers make their life harder using a scroll view when a UITableView would be a better choice. Finally, architecture is crucial for table views. The code of the table view data source often ends inside view controllers when it should go into a separate class.
When the user scrolls back to a row, the table view will request its data again. The tableView(_:numberOfRowsInSection:) method tells the table view how many elements a section contains. The table view uses this information to prepare its scrolling area and display a scroll bar of the appropriate size.
In a scroll view, you need to figure the frame of each subview by yourself. You can use Auto Layout, but that still means you will need a lot of code to set all the constraints. In a scroll view, that’s not as easy to get right as it is in a regular UIView.
Table views are more versatile than you might think. For example, many developers make their life harder using a scroll view when a UITableView would be a better choice. Finally, architecture is crucial for table views.
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!!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With