I can't make swipe gesture work for me in Appium using Java - swipe

I can't made Swipe action work. I did browsed through the web for a few days and found many similar questions but there is no working answer. Also I have tried TouchAction class, doesn't work as well.
I have Appium Version 1.4.13 (Draco) and using Java, TestNG framework.
btw I made scrolling work using (you can use the same logic as a pull to refresh) here is code sample.
public void scrollUp() {
JavascriptExecutor js = (JavascriptExecutor) getDriver();
HashMap<String, String> scrollObject = new HashMap<String,String();
scrollObject.put("direction", "up");
scrollObject.put("element", listElements.get(1).getText());
js.executeScript("mobile: scroll", scrollObject);
}

//Method names explain themselves. I hope it works.
public static void swipeFromRightToLeftMultipleTimes(int howManySwipes) {
JavascriptExecutor js = (JavascriptExecutor) iosDriver;
for(int counter=0; counter < howManySwipes; counter++){
HashMap<String, Integer> swipeObject = new HashMap<String, Integer>();
swipeObject.put("startX", getScreenWidth());
swipeObject.put("startY", getScreenHeight());
swipeObject.put("endX", getScreenWidth()/4);
swipeObject.put("endY", getScreenHeight());
swipeObject.put("duration", 2);
js.executeScript("mobile: swipe", swipeObject);
}
}
public static void swipeFromLeftToRightMultipleTimes(int howManySwipes) {
JavascriptExecutor js = (JavascriptExecutor) iosDriver;
for(int counter=0; counter < howManySwipes; counter++){
HashMap<String, Integer> swipeObject = new HashMap<String, Integer>();
swipeObject.put("startX", getScreenWidth()/4);
swipeObject.put("startY", getScreenHeight());
swipeObject.put("endX", getScreenWidth());
swipeObject.put("endY", getScreenHeight());
swipeObject.put("duration", 2);
js.executeScript("mobile: swipe", swipeObject);
}
}

Is this swipe issue in iOS or Android? Further, is it in real devices or simulators. I couldn't find a solution for iOS simulator for Xcode 7.0.1 with iOS 8.x / 9.0. Please let me know if it works for you.
However, Following is the solution perfectly work in Android real device as well in Android Simulator.
When calling swipeElement method provide element as MobileElement. use like this.. this.swipeElement(driver, MobileElement, 200, 3000); If the scroll length is positive then it scrolls to down, negative then scrolls up.
public void swipeElement(AndroidDriver driver, WebElement element, int scrollLength, int duration){
driver.context("NATIVE_APP");
int bottomY = element.getLocation().getY()+scrollLength;
((AppiumDriver)driver).swipe(element.getLocation().getX(), element.getLocation().getY(), element.getLocation().getX(), bottomY, duration);
}

This solution works in iOS simulator with Appium 1.4.13; Java-Client 3.2.0; Xcode 7.0.1; iOS 8.x / 9.0;
Provide 'elementName' where scroll happens to the element.
JavascriptExecutor js = (JavascriptExecutor) iosDriv;
HashMap<String, String> scrollObject = new HashMap<String, String>();
scrollObject.put("element", ((RemoteWebElement) iosDriv.findElement(By.name("elementName"))).getId());
js.executeScript("mobile: scroll", scrollObject);

driver.context("NATIVE_APP");
Dimension size = driver.manage().window().getSize();
int startx = (int) (size.width * 0.8);
int endx = (int) (size.width * 0.20);
int starty = size.height / 2;
driver.swipe(startx, starty, endx, starty, 1000);
Use above code. Change startx to starty if you wish to swipe in opposite direction.

driver.swipe(startingXCoordinate,StartingYCoordinate,EndXCoordinate,EndYCoordinate,timeForSwipe);
Ex: driver.swipe(100,200,450,200,2000);
here, you are swipe from 100th X coordinate to 450th X coordinate.that is why Y coordinates are same for starting and ending points(200 and 200). The last parameter 2 indicates, swipe action will performs 2 seconds.
Actually we have to mention 2000 milliseconds for 2 seconds.

Related

TouchAction deprecated in Selenium 4

Here is my code to bring the Keyboard on the real ipad devices. Since Touch actions is been deprecated in Selenium 4. Can anyone help with the new solution?
public void tapOnElementToBringKeyboard(By locator) {
TeasyElement element = element(locator);
clickActions(locator);
int fromX = element.getLocation().getX();
int fromY = element.getLocation().getY();
TouchAction touchAction = new TouchAction((IOSDriver<?>) getDriver());
touchAction.tap(PointOption.point(fromX, fromY)).release().perform().tap(PointOption.point(fromX, fromY)) .release().perform();
}
Dont have any solution

Unable to Zoom Out of screen using Selenium WebDriver

Am trying to zoom out of my current page as some of the monitors are quite small there our application is not loading properly.
Selenium 3.141.59
Java 1.8
This is my sample code:
public class ScreenResolutionCheck {
static WebDriver driver = null;
public static void main(String[] args) {
int width = 1512, height = 982; //Default Macbook Pro Size
WebDriverManager webDriverManager = WebDriverManager.chromedriver().browserInDocker().enableVnc().linux().dockerScreenResolution(width + "x" + height +"x24").timeout(100);
driver = webDriverManager.create();
BaseFunctions.logInfoWithOutScreenShot("VNC Url",webDriverManager.getDockerNoVncUrl().toString());
driver.get("https://opensource-demo.orangehrmlive.com/");
driver.findElement(By.tagName("body")).sendKeys(Keys.chord(Keys.COMMAND, Keys.SUBTRACT));
findElement(By.id("txtUsername")).sendKeys("Admin");
findElement(By.id("txtPassword")).sendKeys("admin123");
findElement(By.id("btnLogin")).click();
findElement(By.id("menu_admin_viewAdminModule")).click();
findElement(By.id("tableWrapper"));
driver.quit();
webDriverManager.quit();
}
public static WebElement findElement(By by) {
WebElement we = new WebDriverWait(driver, 30).until(d -> d.findElement(by));
return we;
}
}
I tried the following:
driver.findElement(By.tagName("body")).sendKeys(Keys.chord(Keys.COMMAND,Keys.SUBTRACT));
driver.findElement(By.tagName("body")).sendKeys(Keys.chord(Keys.COMMAND,Keys.SHIFT,Keys.SUBTRACT));
driver.findElement(By.tagName("body")).sendKeys(Keys.chord(Keys.COMMAND,"-"));
new Actions(driver).sendKeys(driver.findElement(By.tagName("body"),Keys.chord(Keys.COMMAND,Keys.SUBTRACT)).build().perform();
js.executeScript("arguments[0].dispatchEvent(new KeyboardEvent('keydown',{'key':'Meta'}))",we);
js.executeScript("arguments[0].dispatchEvent(new KeyboardEvent('keydown',{'key':'+'}))",we);
js.executeScript("arguments[0].dispatchEvent(new KeyboardEvent('keyup',{'key':'Meta'}))",we);
js.executeScript("arguments[0].dispatchEvent(new KeyboardEvent('keyup',{'key':'+'}))",we);
options.addArguments("force-device-scale-factor=0.75");
options.addArguments("high-dpi-support=0.75");
WebDriver driver = new ChromeDriver(options);
Only this one worked but its not optimal as the moment I navigate to next screen, the zoom gets resetted.
js.executeScript("document.body.style.zoom='80%'");
I followed all these links but none worked for me. Any help would be much appreciated.
StackOverflowQuestion
Also Robot class doesn't suit me as I had to run in different OSes.

Adding x number Markers to Codenameone MapContainer at runtime

I have retrieved a large number of latlong values and stored in an ArrayList. I want to add markers to my MapContainer using the latlong values in the ArrayList. The challenges however is that the pins are never positioned correctly on the map (simulator and device). I have tried everything but still no success. Here is a working example. This works but the pins are positioned wrongly at runtime.
Form hi = new Form("cReporter", new BorderLayout());
hi.setScrollableY(false);
Container n = new Container(new BorderLayout());
MapContainer mc = new MapContainer();//
mc.setShowMyLocation(true);
hi.add("Center", mc);
List lx = new ArrayList();
addPoints(lx);
hi.show();
addMarkers(mc, lx);
public void addPoints(List lx)
{
Map m= new HashMap();
m.put("long", 8.993082);
m.put("lat", 38.747393);
lx.add(m);
m= new HashMap();
m.put("long", 8.988419);
m.put("lat", 38.727094);
lx.add(m);
m= new HashMap();
m.put("long", 8.991724);
m.put("lat", 38.775203);
lx.add(m);
}
public void addMarkers(MapContainer mc, List coordList)
{
Style s = new Style();
s.setFgColor(0xff0000);
s.setBgTransparency(0);
FontImage markerImg = FontImage.createMaterial(FontImage.MATERIAL_PLACE, s, 5);
for(Object m: coordList)
{
Map p= (Map)m;
Coord moscone = new Coord(Double.parseDouble(p.get("lat").toString()), Double.parseDouble(p.get("long").toString()));
mc.addMarker(EncodedImage.createFromImage(markerImg, false), mc.getCameraPosition(), "Hi marker", "Optional long description", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("Bounding box is "+mc.getBoundingBox());
ToastBar.showMessage("You clicked the marker", FontImage.MATERIAL_PLACE);
}
});
mc.setCameraPosition(moscone);
mc.revalidate();
}
}
I'm guessing that you aren't using the correct projection lat/long values for the map as these vary based on different implementations. See this for discussion of the different types of positioning: Source event strange latitude & longitude
I notice you create a new encoded image for every marker position. This is very inefficient as every such image would take up RAM and doing it x100 could introduce a serious overhead. This is an image you should reuse.

How to take a screenshot of a scrollable in Selenium using Java?

I am a beginner in Selenium.
I have very long scroll-able form which will automation script will fill, is there a way where I can take screenshot when the page is scrolled down every time (web-driver scrolls to fill the form, I haven't scripted to scroll down as web-driver takes care of it), so that the entire form can be captured in multiple screenshots.
Here is how I would do it. On every swipe You can take screenshot, like as step screenshot.
Here is part of code for screenshot take:
public static String takeScreenshot(WebDriver driver) {
driver.get("http://www.google.com/");
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
// Now you can do whatever you need to do with it, for example copy somewhere
File dest = new File("c:\\tmp\\screenshot.png");
FileUtils.copyFile(scrFile, dest);
return dest.getAbsolutePath();
}
And here is the code for vertical swipe:
public static void swipeVertical(WebDriver driver) {
Dimension size = driver.manage().window().getSize();
System.out.println(size);
int starty = (int) (size.height * 0.70);
int endy = (int) (size.height * 0.30);
int startx = size.width / 2;
new TouchAction(driver)
.press(startx, starty)
.waitAction(Duration.ofMillis(1000))
.moveTo(startx, endy)
.release()
.perform();
}
so my pseudo code would look like this:
WebDriver driver = initDriver();
load page and elements
inputText(text);
takScreenShot(driver);
swipe(driver);
...
repeat until end...
You can capture as many screenshots as you want. After fill in each column, after fill in each third column, whatever.
Or you can let the webdriver fill in the whole form and scroll up/down using press pgup/pgdn simulation:
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
Robot rob = new Robot();
rob.keyPress(KeyEvent.VK_PAGE_DOWN);
rob.keyRelease(KeyEvent.VK_PAGE_DOWN);

WPF Image Generation using an N x N grid of images

I'm working on a personal project that creates an single image from a grid of images. It takes a while to generate the image and doesn't refresh everytime only once the code is done executing. How can the make the interface still functional (not locked up) when its generating the image.
So to start:
I have a N x N grid of identifiers, based on the identifier I draw a specific image at (x,y) with a given scaled height and width.
This image is regenerated each iteration and needs to be updated on the WPF. It is also bound to the ImageSource of the Image on the xaml side
My issue is 'How do I improve performance of generating this large image' and 'How do I refresh the image as many times as I need to (per generation).
for (int i = 0; i < numberOfIterations; i++)
{
// Do Some Work
UpdateImage();
}
...
BitmapImage imgFlower = new BitmapImage(new Uri(#"Images\Flower.bmp", UriKind.Relative));
BitmapImage imgPuppy = new BitmapImage(new Uri(#"Images\Puppy.bmp", UriKind.Relative));
ImageSource GeneratedImage{ get{ GenerateImage(); } set; }
...
void UpdateImage() { OnPropertyChanged("GeneratedImage"); }
...
ImageSource GenerateImage()
{
RenderTargetBitmap bmp = new RenderTargetBitmap(223, 223, 96, 96, PixelFormats.Pbgra32);
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
{
double scaleRatio = CalculateScaleRatio();
DrawGridOfImages(drawingContext, scaleRatio);
}
bmp.Render(drawingVisual);
return bmp;
}
...
DrawGridOfImages(...)
{
double x,y;
for (int r = 0; r < NumberOfRows; r++)
{
x = r * scaleRatio;
for (int c = 0; c < NumberOfColumns; c++)
{
y = c * scaleRatio;
switch (imageOccupancy[r, c])
{
case Flower: drawingContext.DrawImage(imgFlower, new Rect(x,y,scaleRatio,scaleRation));
case Puppy: drawingContext.DrawImage(imgPuppy, new Rect(x,y,scaleRatio,scaleRatio));
}
}
}
}
There are two ways. To first and most beneficial would be to improve the perceived performance, do this by generating the image on a worker thread and use events to update the image on the UI thread at key points so your users can see the progress.
To improve actual performance, if you are targeting and using multicore systems you can try parallel functions if your iterations can actually be performed in parallel. This will require some work and a different mindset but will help if you put the effort in. I'd recommend studying PLINQ to get started.

Resources