Element not found for Input elements on Selenide + Appium - kotlin

I'm writing Android Web automated test using Kotlin+Selenide+Appium. There's already working Desktop Web version of those tests on Kotlin+Selenide.
Koltin 1.2.31
Selenide:4.11.1
Appium:java-client:5.0.4
Appium: 1.7.2
Test starts, appium server starts, browser on my device starts, page opens, element is located but it cannot setValue for it. Test works well except for Input elements and manipulations on it.
In test, I clear the field at first, then I set value for it. It actually find the element, clears it and then throws the error on that step (clear the field). So it clears the field but it also cannot found it???
Errors that appear:
Element not found {.project-scope-main-header-content-input > div > input}
Expected: exist
Caused by: WebDriverException: unknown error: call function result missing 'value'
I tried to run the tests with and without these 2 capabilities:
capa.setCapability("unicodeKeyboard", true)
capa.setCapability("resetKeyboard", true)
Appreciate any help. Thanks.
EDIT: The problem is in outdated ChromeDriver which I cannot update for some reasons.
EDIT#2:
Here's how I initialize it:
`
lateinit var driver: AppiumDriver<SelenideElement>
private val appiumServer = AppiumRunAndStop()
#BeforeClass
#Parameters("platform")
fun setUp(platform : String) {
appiumServer.restartServer()
when (platform) {
"Android" -> {
val capa = DesiredCapabilities()
capa.setCapability("automationName", "Appium")
//capa.setCapability("newCommandTimeout", 150)
capa.setCapability("platformName", "Android")
capa.setCapability("platformVersion", "8.1.0")
capa.setCapability("deviceName", "Nexus 6P")
capa.setCapability("browserName", "Chrome")
capa.setCapability("unicodeKeyboard", true)
capa.setCapability("resetKeyboard", true)
capa.setCapability("chromedriverExecutable", "pathh\\chromedriver_win32\\chromedriver.exe")
driver = AppiumDriver(URL("http://127.0.0.1:4723/wd/hub"), capa)
sleep(2000)
WebDriverRunner.setWebDriver(driver)
}
"iOS" -> {
//TO DO
}
else -> println("Platform is not correct")
}
Configuration.baseUrl = "my_url"
}`
It works with this capa.setCapability("chromedriverExecutable", "pathh\\chromedriver_win32\\chromedriver.exe") but I want it to autoupdate the ChromeDriver automatially.

Did you tried using element.sendKeys("your value") method to enter values and element.clear() to clear the text from the element?
This approach works for me. Also avoid using beta version of Appium Java client and always use a stable version which is 5.0.4.

I found the problem. My test uses outdated ChromeDriver (chromedriver=2.33.506120).
I don't know how to update it for this test.
WebDriverManager.chromedriver().version("2.37").setup() doesn't help.
System.setProperty("webdriver.chrome.driver","path\\chromedriver_win32\\chromedriver.exe") either doesn't help.
I also tried to do this:
val options = ChromeOptions()
options.addArguments("androidPackage", "com.android.chrome")
capa.setCapability(ChromeOptions.CAPABILITY, options)`
EDIT: Worked with capa.setCapability("chromedriverExecutable", "PATH") but why Selenide doesn't update ChromeDriver by itself?

Related

Unable to handle disabled element using selenium when there is no disabled attribute present

I have tried using isEnabled() but because its not a button and there is no disabled attribute present it always returns me true.
I have pasted code by inspecting, Please help me out in this,
9:29 AM
Click on this to see the code
It seems like your class name update with the "disabled" text when its disabled. So you can try bellow method.
<<<<<<<<Imports>>>>>>>>
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
<<<<<<<<Code>>>>>>>>
//get class value of the element
attribute = WebUI.getAttribute(findTestObject('<<Element Locator>>'), 'class')
boolean isSubstringPresent(String subString, String fullString) {
return fullString.contains(subString)
}
//this will print true if the disabled text included in the class
println isSubstringPresent("disabled", attribute) // true
Mostly you can return correct boolean from above print. If it works use IF condition and plan your work.
If the above method not works I would like to suggest to run bellow Javascript in your browser and check its output.
document.getElementByClassName("sc-AxhUy irOhyl bigtix-session bigtix-session--available bigtix-session--disabled").disabled
If it works you can execute the same in your automation, however I'm not familiar with Katalon Studio and found that following code will work for you.
<<<<<<<<Imports>>>>>>>>
import org.openqa.selenium.WebDriver as WebDriver
import org.openqa.selenium.JavascriptExecutor as JavascriptExecutor
import com.kms.katalon.core.webui.driver.DriverFactory as DriverFactory
<<<<<<<<Code>>>>>>>>
WebDriver driver = DriverFactory.getWebDriver()
JavascriptExecutor js = ((driver) as JavascriptExecutor)
String disabledState = js.executeScript(‘sc-AxhUy irOhyl bigtix-session bigtix-session--available bigtix-session--disabled").disabled’)
print(disabledState)
As I can see in your attached image, there is one attribute aria-disabled = true, You can always check against that attribute for checking whether it is enabled or disabled.

How to address "OpenQA.Selenium.WebDriverException: target frame detached" using Selenium through C#

Since chrome updated to version 80 I started getting:
OpenQA.Selenium.WebDriverException: target frame detached
error from the chrome webdriver, when trying to switch frames.
Even driver.switchTo().defaultContent(); doesn't work. It throws a timeout.
Is there any way to avoid or recover from this exception?
This error message...
WebDriverException: target frame detached
...implies that a resultant HttpServerResponseInfo was net::HTTP_NOT_FOUND.
Details
As per the discussion Some error codes are not standard compliant there are some Chrome-specific error codes which still exists and most clients will treat them as unknown error. These error codes are:
target frame detached
chrome not reachable
disconnected
forbidden
no such execution context
tab crashed
This issue was addressed through the bug / commit and the current status is ToBeReleased.
Deep Dive
The error target frame detached is defined in case kTargetDetached where case kTargetDetached is defined in http_handler.cc and occurs when the HttpServerResponseInfo contains HTTP_NOT_FOUND as follows:
void HttpHandler::HandleCommand(
const net::HttpServerRequestInfo& request,
const std::string& trimmed_path,
const HttpResponseSenderFunc& send_response_func) {
base::DictionaryValue params;
std::string session_id;
CommandMap::const_iterator iter = command_map_->begin();
while (true) {
if (iter == command_map_->end()) {
if (w3cMode(session_id, session_thread_map_)) {
PrepareResponse(
trimmed_path, send_response_func,
Status(kUnknownCommand, "unknown command: " + trimmed_path),
nullptr, session_id, true);
} else {
std::unique_ptr<net::HttpServerResponseInfo> response(
new net::HttpServerResponseInfo(net::HTTP_NOT_FOUND));
response->SetBody("unknown command: " + trimmed_path, "text/plain");
send_response_func.Run(std::move(response));
}
return;
}
if (internal::MatchesCommand(
request.method, trimmed_path, *iter, &session_id, &params)) {
break;
}
++iter;
}
and most possibly the reason in your case is kTargetDetached:
case kTargetDetached:
response.reset(new net::HttpServerResponseInfo(net::HTTP_NOT_FOUND));
break;
Solution
To switch Selenium's focus within an <iframe> you have to induce WebDriverWait for the desired frame to be available and switch to it as follows:
Using CssSelector:
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.CssSelector("iframe#twitter-widget-0")));
Using XPath:
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.XPath("//fieldset[#id='twitter-widget-0']")));
Reference
You can find a couple of relevant discussions in:
How to wait for a frame to load before locating an element?
How to locate and click on an element which is nested within multiple frame and frameset through Selenium using Webdriver and C#
Outro
Ways to deal with #document under iframe
I also faced the same issue. Try to update the chromedriver version 80.0.3987.16 with selenium. Switching to iFrame should work fine. It works for me.

PayPal Sandbox not able to find password field

I'm currently using HtmlUnitDriver, and while I am able to set the username, I keep getting an error that Selenium could not find the password field. I am using JavascriptExecutor to set these values inside the PayPal sandbox form, but I'm still unable to get past the password step.
HtmlUnitDriver driver = new HtmlUnitDriver(BrowserVersion.CHROME)
JavascriptExecutor executor = (JavascriptExecutor)driver
driver.setJavascriptEnabled(true)
driver.get(url)
log.debug "setting username"
Thread.sleep(5000)
if(driver.findElement(By.xpath("//*[#id='email']")).displayed){
executor.executeScript("document.getElementById('email').value = 'email';")
log.debug "Username was set"
} else {
log.debug "We never set the username!"
}
if(driver.findElement(By.xpath("//*[#id='password']")).displayed){
executor.executeScript("document.getElementById('password').value='password';")
} else {
log.debug "We never set the password."
}
I understand that I am setting sleeps in there, and that's bad practice for Selenium testing, but I'm pretty much at my wits end here. The url in that case is the link to express checkout, which is something like this: https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=#################
Any help would be greatly appreciated!
As I mentioned earlier, there are multiple issues here:
When I load the initial page, I see this UI:
As you see, Password button is really invisible. So unless we click the Next button, there's no chance that this script will work.
So the following has to be added in order to achieve any kind of progress:
driver.findElement(By.id("btnNext")).submit()
However unfortunately I cannot get this button to be clicked correctly with HtmlUnitDriver. It seems button is clicked, but nothing happens, so Password field remains hidden. However as soon as I switch to ChromeDriver, this is not an issue anymore, and the same code works. So I guess you've hit one of the HtmlUnitDriver limitations, and need to use Chrome or Gecko driver.
Finally a few adjustments to the code will make it more reliable and faster. Here's the final version that works for "real" browsers (Chrome or Gecko):
WebDriver driver = new ChromeDriver()
WebDriverWait wait = new WebDriverWait(driver, 10)
driver.get(url)
// The following line waits for email field to appear. It's more economical and reliable than Thread.sleep
WebElement email = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("email")))
log.debug "setting username"
email.sendKeys("email#gmail.com")
log.debug "Username was set " + email.getAttribute("value")
driver.findElement(By.id("btnNext")).submit()
// Here again using the same method to verify when password becomes visible
WebElement password = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("password")))
log.debug "setting password"
password.sendKeys("password")
log.debug "Password was set " + password.getAttribute("value")
(note: I wrote this code in Java, so I hope I translated all correctly, but if I didn't feel free to fix it)
The result of this script looks like this in Chrome:
With HtmlUnitDriver, script will show an error:
org.openqa.selenium.TimeoutException: Expected condition failed: waiting for visibility of element located by By.id: email (tried for 10 second(s) with 500 MILLISECONDS interval)

Selenium contextClick() hangs on Edge browser

System.setProperty("webdriver.edge.driver","C:\\EdgeDriver\\" + "MicrosoftWebDriver.exe");
WebDriver driver = new EdgeDriver();
driver.navigate().to("http://www.google.com");
new Actions(driver).moveToElement(driver.findElement(By.id("lst-ib"))).contextClick().build().perform();
if (driver != null) {
driver.close();
}
When I run the above code, a context menu is popped up, but it does not proceed further from that. If I manually click on somewhere else, it proceeds further into the program.
I have checked with other browser/driver, it works without any
problem.
I am using Selenium 2.53 and MicrosoftWebDriver 14393
Any solution for this?
try System.setProperty("webdriver.edge.driver","C:\EdgeDriver\MicrosoftWebDriver.exe");
instead of
System.setProperty("webdriver.edge.driver","C:\EdgeDriver\" + "MicrosoftWebDriver.exe");

jQuery.Deferred exception: The string did not match the expected pattern

I've a little headache with this console error, ONLY on Safari (working on MacBook actually).
I have this function:
function exists(element){
var exists = document.querySelector(element);
return exists;
}
invoked inside another function:
function includeHoverStylesheet(){
var path = $("body").attr("data-hover");
if (!("ontouchstart" in document.documentElement || exists("link[href='" + path + "'"))) {
var link = document.createElement("link");
link.rel = "stylesheet", link.href = path, document.head.appendChild(link) && document.body.removeAttribute("data-hover");
}
}
Now, on Chrome works like a charm, but on Safari the console throw this error:
1) Invalid CSS property declaration at: *
2) jQuery.Deferred exception: The string did not match the expected pattern.
3) SyntaxError (DOM Exception 12): The string did not match the expected pattern.
Someone have idea what hell happening???
Thanks in advance guys!
There is a closing bracket missing, so you are using an invalid selector. (as Roamer-1888 mentioned as comment)
Having a look at the following discussion where invalid selectors in different browsers has been tested, only Safari is that strict bringing up errors:
https://www.reddit.com/r/firefox/comments/5nbmqi/on_handling_invalid_selector_strings/
For all jquery-Users: check your jquery version, as there has been bugfixes on selector issues.
I had the same error only on Safari on this statement
var div = $('<div class="abc">');
A statement working fine on Firefox and Chrome, but not on Safari when using version jquery 1.11.1; but working fine in all of them with jquery 1.12.4.
In my case I solved it using the following syntax:
var div = $('<div>', {"class":"abc"});