How to scroll the page in Appium + Python - appium

I create tests using Appium+Python to test IOs app.
I want to scroll the page.
Here is the code
def scroll_page(self):
action = TouchAction(self)
action.press(BrowsePageElements.firs_element_to_scroll(self)).
move_to(BrowsePageElements.second_element_to_scroll(self)).perform()
When I'm trying to run this function, I get an error
error screenshot
Could you help me to find out, how to fix this error?

Appium Python has a native scroll function. It works for both Android and iOS.
driver.scroll(origin_el, destination_el, duration=None), where duration is an optional argument. This function scrolls origin_el to the location of destination_el.
Link to scroll source code
The Appium documentation is rather spotty and needs updating. However, the source code is documented well enough to understand and learn the program.

This currently works for me:
...
SCROLL_DUR_MS = 3000
...
window_size = self.driver.get_window_size()
self.scroll_y_top = window_size['height'] * 0.2
self.scroll_y_bottom = window_size['height'] * 0.8
self.scroll_x = window_size['width'] * 0.5
...
def scroll_up(self):
self._y_scroll(self.scroll_y_top, self.scroll_y_bottom)
def scroll_down(self):
self._y_scroll(self.scroll_y_bottom, self.scroll_y_top)
def _y_scroll(self, y_start, y_end):
actions = TouchAction(self.driver)
actions.long_press(None, self.scroll_x, y_start, SCROLL_DUR_MS)
actions.move_to(None, self.scroll_x, y_end)
actions.perform()
It scrolls slowly over 3s because I want it to be controlled, but you could shorten SCROLL_DUR_MS (the duration of the scroll action in milliseconds) if you want something more zoomy. I also went away from using elements as the start and/or end points because I wanted something general that would work with any screen content.
For scroll_y_top and scroll_y_bottom I picked 20% in from the top and bottom of the screen just to make sure I wasn't hitting anything at the borders (like the navigation bar at the top of iOS Preferences or an info bar at the bottom of the app I was working in). I also ran into a "bug" where it wasn't scrolling when I left scroll_x as 0, but it turns out that it wasn't registering the left edge as inside the scrolling area for the app I was working in.
Hope this helps.

In the past when i've run into issues scrolling for one reason or another, I've simply swiped using coordinates to scroll down the page.
self.driver.swipe(100, 700, 100, 150)

Related

Swift / React Native How to know split view / slide over app's position relative to the whole screen?

I'm making a react-native based app, and I can partially use Swift code by react-native's NativeModule feature.
My app will be used as Split view / Slide over mode in iPad, and I want to know if my app is in the left-side, right-side, or Slide-over.
I could get width and height, also origin (CGPoint) by this code.
let window = UIApplication.shared.windows.first
// Then getting X, Y like this...
window.frame.origin.x
Now my app has only one webview, made by react-native-webview.
So I guess, since the webview is the whole content of the app, and it fills app 100%, so it always returns app.
I want to know, not in webView's perspective, but in app's perpective, the POSITION relative to the screen.
For example, if my iPad width is 1400, and if my app is on the half right side, x should be 700.
And if it is on left side, it should be 0.
I really struggled this, but couldn't find any solution.
FYI, I drawed a diagram for this question.
As I wrote on the above, I tried UIApplication.shared.windows.first.frame.
But it only show the CGPoint of webview, not app relative to the screen.
There is no API for getting 'X' or 'LEFT' in react-native-dimension too.
onLayout also not helpful.

Appium Touch Actions 'Press' and 'Move To' is not working in iOS chrome app

I am learning mobile automation and I came across a scenario some thing like this
Launch chrome app in iOS
Load https://www.google.com
Hold/Press and pull down banner web element on the web page which will display some overlay with three options 'New tab, Reload & Close tab' (note: overlay will lost on releasing the banner web element)
Tap on the new tab button
So far I have written below script in python
def Test(self, driver_provider):
single_tap = appium.webdriver.common.touch_action.TouchAction(driver_provider.driver)
element = driver_provider.driver.find_element_by_accessibility_id('NTPHomeFakeOmniboxAccessibilityID')
single_tap.tap(element=element).perform()
element.send_keys('https://www.google.com')
single_tap.tap(element=driver_provider.driver.find_element_by_accessibility_id('Go')).perform()
time.sleep(1)
#Press banner and pull down will display the over scroll actions
#Then move to left to tap on the add button
banner_element = driver_provider.driver.find_element_by_accessibility_id('banner')
screen_size = driver_provider.driver.get_window_size()
height = screen_size.get('height')
width = screen_size.get('width')
single_tap.press(banner_element, x=banner_element.size.get(
'width')/2, y=banner_element.size.get('height')/2).wait(1).move_to(banner_element,
x=width/2, y=height/2).wait(0.5).move_to(banner_element, x=0, y=height/2).release().perform()
for some reason press and move_to actions are not happening and there is no error returned as well, I am not clear what went wrong here. Please share your view on what went wrong thanks.
it's failing to perform press and move to because of wait value is very small. When I use the wait(500) then the press and move to is happening.
single_tap.press(banner_element, x=banner_element.size.get(
'width')/2, y=banner_element.size.get('height')/2).wait(500).move_to(banner_element,
x=width/2, y=height/2).wait(500).move_to(banner_element, x=0, y=height/2).wait(500).release().perform()

Appium::TouchAction.new.tap doesn't work correctly

And(/^I click OK button in popup$/) do
#Appium::TouchAction.new.tap(x:0.64, y:0.57, count: 1).perform
Appium::TouchAction.new.tap(x: 270, y: 506,count: 1).perform
end
And(/^I click Allow button in popup$/) do
#Appium::TouchAction.new.tap(x:0.64, y:0.57, count: 1).perform
Appium::TouchAction.new.tap(x: 270, y: 506,count: 1).perform
end
Given the next code, I work with Appium 1.9.1, Ruby 2.3.7 and Cucumber to automate iOS app, if I'm passing relative coordinates (percentage) - then appium doesn't perform any taps, but, if I comment out lines with absolute coordinates and comment lines with relative coordinates - all taps will work. The strangest thing is that if I use relative coordinates in 1st line and absolute coordinates in second line - it will perform first tap, but won't perform second.
My goal is to use relative coordinates everywhere, so tests will be usable on devices with any screen resolution, please advice, if there are any known solutions to use relative coordinates (or if I'm doing smth wrong)
After going through your code snippet, I assume you are dealing with alert pop-up in iOS device.
In iOS, with Appium Java client, I can deal with pop-up using traditional driver.switchTo().alert();.
Here driver refers to IOSDriver.
I'm sure there must be equivalent to this in Ruby as well.
Try using Alert class to accept the alerts instead of tapping on the coordinates.

Appium: How to wait for new element with same name as visible one to appear on screen?

We're using Appium with iOS Simulator and test functions written in Java.
We have an iOS App with screen 1 containing a UICollection view, and tell Appium to click on one of its elements.
This opens screen 2 (and the scrolling animation takes about 500 ms), which also contains an UICollection view. I want to find out the size of the UICollection view of the second screen with Appium.
The problem is that Appium is too fast and executes the findElements() method directly after the click, which causes it to find the UICollection view of the first screen.
clickOnElementOnFirstScreen();
webDriver.findElements( By.className( "UIACollectionCell" ) ).size();
// is supposed to find the UICollection view on the second screen,
// but actually finds the UICollection view on the first screen
Appium provides several waiting functions. However as far as I can see all of them are intended to be used in this fashion:
"wait until element at location X / with name X becomes visible"
If I try to use these waiting functions, they don't wait at all because they immediately find the UICollection view of the first screen, which has the same location and name as the one on the second screen.
The only solution I have found is to use Thread.sleep:
Thread.sleep(1000);
webDriver.findElements( By.className( "UIACollectionCell" ) ).size();
But we don't want to use Thread.sleep in code that will run on the client's server on hundreds of tests.
We might be able to modify the App and enter metadata into the views so that Appium is able to distinguish them, but this situation occurs in several places and the App is being programmed by the client, so we want to avoid this too.
What is a simple and safe way to wait for the new screen to appear, without modifying the code of the iOS App?
I have found only dirty workaround for this issue.
static waitFor(Duration duration) {
try {
def WebDriverWait wait = new WebDriverWait(mobileDriver, duration.standardSeconds)
wait.until(visibilityOfElementLocated(By.xpath("//Fail")))
//Wait until false case is visible to ensure proper timeout
} catch (Exception e) {
}
}
Another workaround/solution that has been posted on the Appium forums is:
First search for some other element that distinguishes the 2. screen from the 1. screen; once that is visible, it's safe to search for the originally desired element.

iPad parallax flickering

I am using a parallax effect with javascript but I'm having issues with iPad.
I know the "$(window).scroll" is not triggered on webkit touch devides - only when we release the screen - so i'm using:
window.addEventListener("touchmove", triggerScroll, false);
function triggerScroll(event)
{
var scrollTop = $(window).scrollTop();//event.touches[0].pageY; //window.pageYOffset();
$("#allCanvas .divCanvas").each(function(index, element) {
var speed = $(element).data('speed');
var initialTop = $(element).data('initialtop');
$(element).css('top', initialTop-(scrollTop*speed));
});
}
The problem is that it flickers the .divCancas a few pixels to the top or bottom depending if I'm scrolling to top or down.
I tracked the TOP value passed on $(element).css('top', initialTop-(scrollTop*speed)); and it's every time correct. The correct "TOP" value, eventhough webkit move it for a few milleseconds to the wrong position.
I tried also:
-"margin-top" rather than "top" with no difference.
-Removing all other objects and making the ".each" loop through only one div, so I guess is not a jQuery performance issue.
Has anyone came across this problem?
Many thanks
Diego
Maybe try using some of the -webkit css animation features... these run very smoothly on iOS devices. Here's a great demo of that (webkit only): http://jibjub.com/demo/HTML5/cube.html

Resources