How run a Query on an Element? - selenium

Issue and how I would do it with the plain Selenium API
I often need to query an element on the page (say with cssSelector().element), use it, and then want to find a descendent element. With the plain Selenium API, I would write something like:
val foo = webDriver.findElement(By.cssSelector(".foo"))
val bar = foo.findElement(By.cssSelector(".bar"))
How can I do this with the ScalaTest Selenium DSL? I can get the "foo" element with:
val foo = cssSelector(".foo").element
But then how to get "bar" from "foo"? Of course, I could just use the Selenium API in that case (i.e. val bar = foo.underlying.findElement(By.cssSelector(".bar"))), but end up with a WebElement instead of a ScalaTest Element.
Workaround running another query
For now, I just run the query all over again, as shown below, but find this verbose, less clear, and not always equivalent to just looking for elements under an element.
val fooSelector = cssSelector(".foo")
val foo = fooSelector.element
val boo = cssSelector(fooSelector.queryString + " .bar").element

The cssSelector method creates a CssSelectorQuery object. You can pass that object as an argument to the find method:
val foo = find(cssSelector(".foo")).get

Related

Kotlin Java streams - map Selenium WebElement(s) to List

I'm struggling a bit with a pretty simple case of mapping a list of Selenium WebElements to a List of classes using Java Streams.
The element:
val elements: List<WebElement> = element.findElements(By.cssSelector("[data-e2e-selector=expense]"))
(Currently, there are only two elements in the list.)
I'm currently mapping the WebElement list to a MutableList of classes the "classic way":
val expenseElements: MutableList<ExpenseElement> = ArrayList()
for (element in elements) {
expenseElements += ExpenseElement(element)
}
Which is working fine. But I feel I should learn to use Stram() to do this more "elegantly". Or, at least, because I want to :-)
But my feeble attempt at using Stream()
val expenseElements = elements.stream().map { UtgiftElement(element) }.collect(Collectors.toList())
results in only the first element being included. So the first elements takes up both places in the the list.
The first method:
expenseElements[0].expense() = "Entry 1"
expenseElements[1].expense() = "Entry 2"
The non-working Stream() method:
expenseElements[0].expense() = "Entry 1"
expenseElements[1].expense() = "Entry 1"
This is basic I know, but I've tried replicating code that does the same in Java. I have to start somewhere.
There's a mistake in your mapping lambda. You do:
map { UtgiftElement(element) }
But that is not correct. The map function provides you with a single input, named it by default. Your lambda should either by map { UtgiftElement(it) } or map { element -> UtgiftElement(element) }.
I do not know where your element variable comes from, but I think it is not one of the elements in the stream.

How do I add a variable to ::class.java when using an Intent?

private fun showMember(member: Member) {
val memberN: String = "" + member.name
val moveIntent = Intent(this#MainActivity, memberN::class.java)
startActivity(moveIntent)
}
After some testing I found out that memberN::class.java crashes the app when I run the function. I tried using "" + and $ but it doesn't work.
I'm making a simple app which has a list of people and descriptions of them. When you tap on one of the objects on the list, it brings you to a page where you can read more about the person. As you can see from the code, each page is simply just the name of each person.
To get a Class by its name as a string, use Class.forName() e.g. Class.forName(memberN).

Get unique css selector from WebElement

is it possible to get a css selector of an WebElement?
eg
var optionSelectors = mutableListOf<String>()
val options = selectWebElement?.findElements(By.cssSelector("option")).orEmpty()
for(option in options){
var optionSelector = option.getSelector()
optionSelectors.add(optionSelector)
}
return toJson(optionSelectors)
Thank you in advance
You can always use Reflection to get foundBy property value like:
Field field = element.getClass().getDeclaredField("foundBy");
field.setAccessible(true);
String foundBy = field.get(element).toString();
However the nature of your question is a little bit weird, given you found the element already you should know its selector, shouldn't you? If you want to interact with the Select option values you can go for the relevant Select class which has getOptions() function.
Also consider going for Page Object Model design pattern, it is one of best practices to keep your test logic separate from UI layer

GetAttribute of WebElement in Selenium Firefox Driver Returns Empty

So I have a test that was written, and the test runs and works using the Selenium ChromeDriver just fine. I was tasked with getting the tests working on the FirefoxDriver as well.
Part of the test we input text into a login field, and then check the login field to make sure it was input. The way we check the field is like this
public virtual string Text => WebElement.GetAttribute("value");
while (!Text.Equals(inputText) && count++ < 3)
This works perfectly fine in Chrome. However it does not in Firefox. When I debug the test, it shows that Text is "" or empty/blank. If I open Firefox, I can do this document.getElementById("login").value and it returns the correct value.
Is WebElement.GetAttribute implemented differently in the FirefoxDriver or am I just missing something?
It's hard to say in your case why is not working on Firefox, there is no different implementation between browsers. You can try alternate solution using IJavascriptExecutor instead as below :-
IJavaScriptExecutor js = driver as IJavaScriptExecutor;
string Text = (string)js.ExecuteScript("return arguments[0].value", WebElement);
The Selenium protocol to get an attribute/property has evolved with Selenium 3.
With Selenium 2, the method WebElement.GetAttribute(...) returns the HTMLElement property when present and the attribute otherwise.
With Selenium 3, there's a distinctive command to get the property and one for the attribute :
https://www.w3.org/TR/webdriver/#get-element-property
In your case it seems that you are using the geckodriver (Selenium 3) with a client limited to the Selenium 2 specs. It would explain why the property is not returned.
To make it work, you can either upgrade your C# client to V3.0.0-beta2:
https://github.com/SeleniumHQ/selenium/blob/master/dotnet/CHANGELOG
https://github.com/SeleniumHQ/selenium/commit/a573338f7f575ccb0069575700f2c059dc94c3b8
Or you can implement your own GetProperty in a method extension:
static string GetProperty(this IWebElement element, string property) {
var driver = (RemoteWebDriver)((RemoteWebElement)element).WrappedDriver;
var result = (IList)driver.ExecuteScript(#"
var element = arguments[0], property = arguments[1];
if (property in element) return [true, '' + element[property]];
return [false, 'Missing property: ' + property];
", element, property);
bool succeed = (bool)result[0];
if (!succeed) throw new WebDriverException((string)result[1]);
return (string)result[1];
}
Usage:
string value = driver.FindElement(...).GetProperty("value");

mongo-scala-driver: Getting Results

I have the following document in Mongodb:
{ "index_column" : "site_id", "mapped_column":"site_name"}
I'm using the mongo-scala-driver from my scala code to query the server. How do I get the mapped_column to a scala String variable? I tried with the following code:
val result = mongocollection.find(equal("index_column", data)).first()
It returns a org.mongodb.scala.ObservableImplicits$BoxedObservable#207c9b87
Is it possible to convert the Observable to an Iterator? I just need the mapped_column value in a scala String variable.
Scala driver is completely asynchronous, so you can subscribe for the result. The simplest way is to use foreach:
val result = mongocollection.find(equal("index_column", data)).first()
result.foreach { value => ... }
Another option is to convert Observable to Future:
Await.result(result.toFuture(), 3 seconds)
I resolved this issue by switching the driver to mongodb casbah and it can be done with the following code:
val result = mongocollection.find(MongoDBObject("index_column"-> "site_id")).one()
println(result.get("mapped_column"))