Appium XCUITest iOSDriver sendkeys() not working - java

TLDR:
sendKeys() not working in web application text field, but only with IOSDriver/XCUITest and only on my web app's page. When running the same test in an Android simulator it works fine on my page, and everywhere else that I've tested (google and ask.com search inputs), but when I test in an iOS simulator, sendKeys() does not work on my web app's page, but works everywhere else (google and ask.com) and I have no idea why.
Capabilities config file:
["Safari", "12.2", "iOS", "iPhone Simulator", "XCUITest", "1.12.1"]
The test:
public class AppiumFieldsTest extends TestBase {
#Test(dataProvider = "appium", groups = "Appium", description = "appium fields test")
public void appiumFieldsTest(String browser, String version, String platform, String device, Method method, String automationName, String appiumVersion) throws Exception {
IOSDriver<WebElement> driver;
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability(MobileCapabilityType.PLATFORM_NAME, platform);
caps.setCapability(MobileCapabilityType.PLATFORM_VERSION, version);
caps.setCapability(MobileCapabilityType.DEVICE_NAME, device);
caps.setCapability(MobileCapabilityType.AUTOMATION_NAME, automationName);
caps.setCapability(MobileCapabilityType.BROWSER_NAME, browser);
caps.setCapability("autoAcceptAlerts", true);
caps.setCapability("connectHardwareKeyboard", false);
caps.setCapability("sendKeyStrategy", "oneByOne");
System.out.println(caps);
String url = "http://127.0.0.1:4723/wd/hub";
driver = new IOSDriver(new URL(url), caps);
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
driver.get("https://dev-app.pactsafe.com/sign?r=5cd32b47e89fc12f110449ca&s=5b2a6a597a7a3c1e4fa39c0b&signature=kto0Xohrz52ss7kc5z6t0grRbzUPsg6TrfbCbKtRuC5nQM82lNEhFL-zPgN7LaTvGG8mhuifNSc0nayvch1Rgc858Ptx8yRRD9MWJSoD4mEuHFg7LmJ-FHP~UsVEypv-gwwy-6N14BnhdkN94OZ73Kq9mBfS8QGlYKTqa76uclW0FIdnclRfA8NvK0z8CxjPcA8Luv9orw6Ye7wEuHAGqhqFURa15WeFrjrFKW9PNf6NkLVURNvOwqH4xBsfJubCkETMfjtnD4xT7PFSpgykAuU-Av0HehxCFNCYaHmyj5qvB3l9h7xgm8KKoSOO0c9VH1HpnLtwG6KAwwItawcsjg__");
String textFieldtext = "some random text";
Thread.sleep(10000);
WebElement ele = driver.findElementByXPath("//*[#data-name=\"field-5b6305f656bcff936a3c53ca\"]");
ele.click();
Thread.sleep(3000);
ele.sendKeys(textFieldtext);
Assert.assertEquals(ele.getAttribute("data-value"), textFieldtext);
...
...
...
I am trying to do a .click() then a .sendKeys() on the first field at the top of the page, but it is not sending any text. If you run the test you can see that the field is actually being clicked, as it turns a darker blue color, as expected, but then then the sendKeys() function does nothing. Also, when testing on Android, the keyboard opens on click() but not on iOS.
I've tried all the different sendKeyStratey capabilities and still nothing.
I've tried different iOS simulators and appium/safari versions, and still get the same results.
I've tried setting the connectHardwareKeyboard to true, as well as false, and still the same results.
I've added Thread.sleep() in-between commands - nuthin
And again, testing on android works fine on my app, google and ask, but when testing on iOS, my app does not work, but google and ask do
The appium logs show that it is indeed trying to send the text after successfully finding the element:
[HTTP] {"id":"5000","text":"some random text","value":["s","o","m","e"," ","r","a","n","d","o","m"," ","t","e","x","t"]}
[W3C (bf5882ff)] Calling AppiumDriver.setValue() with args: [["s","o","m","e"," ","r","a","n","d","o","m"," ","t","e","x","t"],"5000","bf5882ff-f1a1-4ce1-bb79-02836762cb88"]
[XCUITest] Executing command 'setValue'
Any and all help/suggestions are greatly appreciated

You can try using one of these options:
setValue() This clears the value before sending the string.
Add maxTypingFrequency capability, this is ONLY for IOS when you notice errors during typing, for example the wrong keys being pressed or visual oddities you notice while watching a test, try slowing the typing down. Set this cap to an integer and play around with the value until things work. Lower is slower, higher is faster! The default is 60.

Related

Selenium chrome driver (Java) click() login button doesn't work programmatically but works manually

I'm just doing some test automation of web UI, specifically this page https://autorefi.capitalone.com/login/
I am locating the lastname, zipcode, ssn input boxes and typing in data (the data here doesn't matter). I am then simply using the locator to click the "Sign In" button. The problem is, everytime I run this within my code (Java) using selenium/chromedriver, I get an error
Sorry, we weren't able to log you in. If you continue to see this error, make sure you're using one of our supported browsers.
The problem is this is not the correct error message. You can try this yourself by simply opening another tab and entering a random lastname, zipcode, and last 4 digit of SSN. Conversely, if you actually had an offer with Capital one, it would bring up a different page completely. The point is, the first error message I posted only comes via selenium and is not correct. The correct error message is:
Sorry, it looks like you don't have an offer with Capital one.
I tried sleeping the thread before clicking the button ,because I thought it was maybe clicking it too fast, but it still didn't work. I a bit perplexed why doing the same set of operations manually seems to work, but launching this programmatically through selenium. Can anyone provide any insight here? My code is:
WebElement element;
WebDriver driver = null;
ChromeOptions options = new ChromeOptions();
options.setPageLoadStrategy(PageLoadStrategy.NONE);
driver = new ChromeDriver(options);
WebDriverManager.getInstance(CHROME).setup();
// TODO: PROD
driver.get("https://autorefi.capitalone.com/login/");
WebElement refiCommonLoginForm = new WebDriverWait(driver,10).until(ExpectedConditions.presenceOfElementLocated(By.tagName("refi-common-login-form")));
WebElement shadowRoot1 = expandRootElement(refiCommonLoginForm, driver);
WebElement refiCommonLastName = shadowRoot1.findElement(By.tagName("refi-common-last-name"));
WebElement refiCommonLastNameShadowRoot = expandRootElement(refiCommonLastName, driver);
WebElement refiCommonZip = shadowRoot1.findElement(By.tagName("refi-common-zip"));
WebElement refiCommonZipShadowRoot = expandRootElement(refiCommonZip, driver);
WebElement refiCommonLastFourSSN = shadowRoot1.findElement(By.tagName("refi-common-last-four-ssn"));
WebElement refiCommonLastFourSSNShadowRoot = expandRootElement(refiCommonLastFourSSN, driver);
refiCommonLastNameShadowRoot.findElement(By.id("loginLastName")).sendKeys("random last name");
refiCommonZipShadowRoot.findElement(By.id("loginZipCode")).sendKeys("43978");
refiCommonLastFourSSNShadowRoot.findElement(By.id("loginLastFourSSN")).sendKeys("3483");
Thread.sleep(2000);
shadowRoot1.findElement(By.tagName("button")).click();
Absolutely not sure the issue is that, but still possibly this will help.
Instead of clicking the "Sign in" button try submitting it i.e. shadowRoot1.findElement(By.tagName("button")).submit()
But I guess the issue here is that this site has some kind of anti bot defense that blocks automated access to it.

Mobile emulator Selenium tests fail in Jenkins but not in cmd

I have a test that always fail when running inside Jenkins.
My project includes Selenium webdriver, JAVA, Maven, TestNG, Jenkins, Allure (reports).
I have a few suites of tests with 100+ test cases, and I iterate them through 3 different browsers (the tests run in parallel using TestNG). They all run (using maven command line) and pass in my development laptop, and on the test server when using a command line.
I have 2 problems regarding Jenkins and separated them into 2 questions- one of them is described in this question, and the other (IE11 issue) is here.
The problem starts when running inside Jenkins in the test server!
The test fail in mobile emulator (Chrome browser) - in the test I click on a link to verify that a new window was opened with the correct url.
I tried 3 types of clicks (Selenium click, Actions, JS) and all returned a null handle.
The code:
Here I create the main window handle and click the link:
String mwh = driver.getWindowHandle();
WebElement poweredBy = (new WebDriverWait(driver,10).until(ExpectedConditions.visibilityOfElementLocated(By.xpath(Consts.POWERED_BY_XPATH_1000))));
poweredBy.click();
And this is, part of, the method that gets the handle and verify the new window:
public boolean closePopupWindow(String mwh, String mTitle, String layoutNumber) {
// For IE11- make sure popup blocker is turned off in the options. else it will have only one window handle and fail
boolean isOpenedWindowCorrect = false;
String newWindow = null;
Set<String> handlers = driver.getWindowHandles();
for (String window : handlers) {
if (!window.equals(mwh)) {
newWindow = window;
}
}
// the focus is on the main page. need to switchTo new page and close it
driver.switchTo().window(newWindow);
System.out.println("The focus now is on the NEW window");
String newTitle = driver.getTitle();
System.out.println(newTitle);
This is the error I'm getting:
java.lang.NullPointerException: null value in entry: handle=null
at com.google.common.collect.CollectPreconditions.checkEntryNotNull(CollectPreconditions.java:34)
at com.google.common.collect.SingletonImmutableBiMap.(SingletonImmutableBiMap.java:42)
at com.google.common.collect.ImmutableBiMap.of(ImmutableBiMap.java:73)
at com.google.common.collect.ImmutableMap.of(ImmutableMap.java:123)
at org.openqa.selenium.remote.RemoteWebDriver$RemoteTargetLocator.window(RemoteWebDriver.java:995)
at il.carambola.pages.Page.closePopupWindow(Page.java:786)
Do you think there is a security issue that Jenkins wont open new windows in the browser? Is it VERY slow to open the window?
The same tests PASS when not using mobile emulator. (I have the same test in Chrome and Firefox and it succeed to click and pass the verification).
JDK 1.8.0_162
Jenkins V 2.121.1
Server- AWS t2.large - 8GB RAM, Windows server 2016 Data center, 64bit
It's clear that when your program gets to this line
driver.switchTo().window(newWindow);
that newWindow is still null. The way this is written, it could be a timing issue, and it could be another issue causing the popup to not show up. To make sure it's not a timing issue, I would suggest adding some kind of wait for there to be multiple window handles before you try to switch windows. Something like
(new WebDriverWait(driver,10)).until(d -> d.getWindowHandles().size() == 2);
If that wait fails, then you know the popup is being blocked and can go from there.

Maximize browser window in LeanFT

I am looking for some solution, like this in Selenium WebDriver:
ChromeOptions options = new ChromeOptions();options.addArgument("--start-maximized");
So browser window should be maximized when test is executed.
I found a profile based solution for this problem, but it opens a lot of tabs, which is maybe caused by escape characters.
#Test
public void chromeWithProfileLaunch() throws Exception {
String profileDir = "--user-data-dir=\"c:\\Temp\\profile1\""; //should be different folder every time
String leanftChromeExtension = "--load-extension=C:\\Program Files (x86)\\HPE\\LeanFT\\Installations\\Chrome\\Extension"; //to load the LeanFT extension
String homePage = "www.google.com"; //the homepage to start with
new ProcessBuilder("C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe", profileDir, leanftChromeExtension, homePage)
.start();
Thread.sleep(2000); //wait for Chrome process to load
Browser openedBrowser = BrowserFactory.attach(new BrowserDescription.Builder().title("Google").type(BrowserType.CHROME).build());
Verify.areEqual(homePage, openedBrowser.getURL());
}
I don't know about maximized but LeanFT supports putting the browser in fullScreen mode.
LeanFT doesn't support maximize() out of the box yet.
However, you could use sendKeys() method.
I'm not entirely sure if you can to it on the browser instance directly, or you need to getPage() first, but you can definitelly send Super key (win key) + ↑ as specified here. ↓ for restoring back to the initial state.
Here's an example using sendKeys with Java SDK if you need it.

How to copy Google Translate's Chinese transliteration using Selenium?

I'm trying to extract Google Translate's pinyin transliteration of a Chinese word using Selenium but am having some trouble finding its WebElement.
For example, the word I look up is "事". My code would be as follows:
String word = "事";
WebDriver driver = new HtmlUnitDriver();
driver.get("http://translate.google.com/#zh-CN/zh-CN/" + word);
When I go to the actual page using my browser, I can see that its pinyin is "Shì" and that its id, according to Inspect Element is src-translit. However, when I go to view source, though the id="src-translit" is present, you don't see anything resembling "Shì" nearby. It's simply empty.
Thinking that the page has had no time to load properly. I implemented a waiting period of 30 seconds (kind of a long wait, I know, but I just wanted to know if it would work).
int timeoutInSeconds = 30;
WebDriverWait wait = new WebDriverWait(driver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("src-translit")));
Unfortunately, even with the wait time, transliteration and its text still returns as empty.
WebElement transliteration = driver.findElement(By.id("src-translit"));
String pinyin = transliteration.getText();
My question, then, is: what's happened to the src-translit? Why won't it display in the html code and how can I go about finding it and copying it from Google Translate?
Sounds like javascript isn't being executed. Looking at the docs, you can enable javascript like this
HtmlUnitDriver driver = new HtmlUnitDriver();
driver.setJavascriptEnabled(true);
or
HtmlUnitDriver driver = new HtmlUnitDriver(true);
See if that makes a difference.
EDIT:
I still think the problem is related to javascript. When I run it using FirefoxDriver, it works fine: the AJAX request is made, and src-translit element has been updated with Shi.
Workaround:
In any case, monitoring the network traffic, you can see that when you want to translate 事 , it makes an AJAX call to
http://translate.google.com/translate_a/t?client=t&sl=zh-CN&tl=zh-CN&hl=en&sc=2&ie=UTF-8&oe=UTF-8&pc=1&oc=1&otf=1&rom=1&srcrom=1&ssel=0&tsel=0&q=%E6%B2%92%E4%BA%8B
Which returns JSON:
[[["事","事","Shì","Shì"]],,"zh-CN",,[["事",,false,false,0,0,0,0]],,,,[],10]
Maybe you could parse that instead for now.

Bring the Firefox Browser to Front using selenium Java (Mac OSX)

I am using three instances of fire fox driver for automation.I need to bring current active firefox browser into front, Because I am using some robo classes for some opertation. I had tried java script alert for google chrome in mac ( same operation) and its worked fine. In windows used user32 lib. In the case of firefox mac its showing the alert in background but the web page is not come into front.
((JavascriptExecutor)this.webDriver).executeScript("alert('Test')");
this.webDriver.switchTo().alert().accept();
The above code I used for chrome in Mac. Same code is working and showing alert for firefox but the window is not coming to front.
Please suggest if there any other method for doing the same in firefox.
Store the window handle first in a variable, and then use it to go back to the window later on.
//Store the current window handle
String currentWindowHandle = this.webDriver.getWindowHandle();
//run your javascript and alert code
((JavascriptExecutor)this.webDriver).executeScript("alert('Test')");
this.webDriver.switchTo().alert().accept();
//Switch back to to the window using the handle saved earlier
this.webDriver.switchTo().window(currentWindowHandle);
Additionally, you can try to maximise the window after switching to it, which should also activate it.
this.webDriver.manage().window().maximize();
Try switching using the window name:
driver.switchTo().window("windowName");
Alternatively, you can pass a "window handle" to the switchTo().window() method. Knowing this, it’s possible to iterate over every open window like so:
for (String handle : driver.getWindowHandles()) {
driver.switchTo().window(handle);
}
Based on the Selenium documentation: http://docs.seleniumhq.org/docs/03_webdriver.jsp
As described in other topics, you can use
driver.manage().window().setPosition(new Point(-2000, 0));
too.
# notifications for selenium
chrome_options = webdriver.ChromeOptions()
prefs = {"profile.default_content_setting_values.notifications": 2}
chrome_options.add_experimental_option("prefs", prefs)
current_path = os.getcwd() # current working path
chrome_path = os.path.join(current_path, 'chromedriver')
browser = webdriver.Chrome(executable_path=chrome_path, chrome_options=chrome_options)
browser.switch_to.window(browser.current_window_handle)
browser.implicitly_wait(30)
browser.maximize_window()
browser.get("http://facebook.com")
Only thing that worked for me on mac: self.driver.fullscreen_window().

Categories