Just a small clarification on using Geb text() vs value().
According to the Geb documentation:
The value text is treated specially as a match against the node’s text.
And for value():
Calling value() with no arguments will return the String value of the first element in the Navigator.
From my understanding through trial-and-error, text() can be used to check/set the text content in a particular element, EXCEPT form elements. value() is used to check/set the content of a form element.
assertThat($("h1").text()).isEqualTo("Geb") // will work
assertThat($("input").value()).isEqualTo("Geb") // will work
assertThat($("input").text()).isEqualTo("Geb") // will not work
Is this correct? Or is there a greater differentiation? I couldn't find any substantial description in the documentation.
Thanks in advance!
You cannot use text() to set anything, it only returns the first element's text content. It basically delegates to WebElement.getText().
The text you quoted:
The value text is treated specially as a match against the node’s text.
Relates to using an attribute selector like `$("div", text: "Lorem ipsum...").
And yes, value() and value(Object) can be use to retrieve and set value/text of an input.
Related
I'm learning how a WebDriver works, and I don't understand how to format the request URL for Find Element From Element.
The element ID of Find Element will return something like this:
{"element-6066-11e4-a52e-4f735466cecf": "e72b0320-5d61-4886-b903-5b2e4bb43d88"}
As I understand it, the above {key: value} format IS the element ID. If that is the case, how does one user that as the {element id} in "POST /session/{session id}/element/{element id}/element"? If {key: value} IS NOT the element ID, what is? And what would a properly formatted request URL look like?
Thanks!
In the above example, the element ID is "e72b0320-5d61-4886-b903-5b2e4bb43d88". It's a bit confusing because rather than creating an object that looks like this:
{"ELEMENT": "e72b0320-5d61-4886-b903-5b2e4bb43d88"}
We have the very odd:
{"element-6066-11e4-a52e-4f735466cecf": "e72b0320-5d61-4886-b903-5b2e4bb43d88"}
What's going on here? It has been deemed from on high that the key which in a JSON object indicates that we are dealing with an element ID is the arbitrary and constant string "element-6066-11e4-a52e-4f735466cecf". The reason is that any non-arbitrary key might end up being a return value of some unrelated JavaScript code. Consider this JavaScript code:
return document.getElementById('foo');
This could be used in ExecuteScript as follows (for example in Python):
driver.execute_script("return document.getElementById('foo');");
What should be returned here? Well we are dealing with an actual HTML element, which can't be converted into JSON and sent back over the wire to the Python client. So instead, WebDriver stores a reference to that element as an ID, and sends that back. But it can't just send back the ID as a string, because there's no way for driver.execute_script to know in advance what sort of thing might be returned. Maybe it's not an element ID--maybe it's some other string related to your application. In the past, the standard format for a JSON WebElement was as I noted above (with the ELEMENT key).
At some point, however, someone must have written some JavaScript code which resulted in a JS object which contained the word ELEMENT as key somewhere inside. This object had nothing to do with WebElements, but when it was returned via a call to driver.execute_script, the client converted it into a WebElement object!
Whether or not this scenario ever actually happened is beside the point; the point is that a simple short word like ELEMENT is ripe for name clashes. The spec authors wanted a way to unambiguously denote that we are dealing with a WebElement even if we encounter it in a serialized JSON format, and in a way that is not likely to clash with other things web developers or testers are doing.
So the most direct answer to your question is, your POST request should look like:
POST /session/{session id}/element/e72b0320-5d61-4886-b903-5b2e4bb43d88/element
I've used both
WebElement.sendKeys('')
and
WebElement.setValue('')
In order to input text into fields. The vast majority of the time they seem to act the same, but I've found a few cases where setValue() works but sendKeys() does not.
All I can find in the Selenium docs is that sendKeys() 'more accurately imitates user input' then setValue(). Does anyone know what is actually happening under the hood?
sendKeys()
sendKeys() is the Java method from WebElement to simulate typing into an element, which may set its value.
Defination:
void sendKeys(java.lang.CharSequence... keysToSend)
Use this method to simulate typing into an element, which may set its value.
Parameters:
keysToSend - character sequence to send to the element
Throws:
java.lang.IllegalArgumentException - if keysToSend is null
Usage:
driver.findElement(By.id("identifierId")).sendKeys("C.Peck#stackoverflow.com");
However there is no setValue() method in Java and the closest match seems to be setAttribute() JavaScript method.
setAttribute()
setAttribute() is the JavaScript method which sets the value of an attribute on the specified element. If the attribute already exists, the value is updated; otherwise a new attribute is added with the specified name and value.
Syntax:
Element.setAttribute(name, value);
Example:
HTML:
<button>Hello World</button>
JavaScript:
var b = document.querySelector("button");
b.setAttribute("name", "helloButton");
b.setAttribute("disabled", "");
Implementation through Java executeScript():
((JavascriptExecutor)driver).executeScript("document.getElementById('elementID').setAttribute('attribute_name', 'new_value_for_element')");
I am trying to extract the text in an input box,
<input type="text" name="inputbox" value="name" class="box">
I started with
input = driver.find_element_by_name("inputbox")
I tried input.getText() but I got
AttributeError: 'WebElement' object has no attribute 'getText'
Use this to get the value of the input element:
input.get_attribute('value')
Note that there's an important difference between the value attribute and the value property.
The simplified explanation is that the value attribute is what's found in the HTML tag and the value property is what you see on the page.
Basically, the value attribute sets the element's initial value, while the value property contains the current value.
You can read more about that here and see an example of the difference here.
If you want the value attribute, then you should use get_attribute:
input.get_attribute('value')
If you want the value property, then you should use get_property
input.get_property("value")
Though, according to the docs, get_attribute actually returns the property rather than the attribute, unless the property doesn't exist. get_property will always return the property.
Why this "value" can not be written as "pricevalue" or other, otherwise input will not convert non-numeric values
In the props element, you are defining the properties your component will attach to. You can call them whatever you want. You need to be clear about a couple of things...
You define the name here in camelCase, but when you call the component in the parent markup, use kebab-case.
methods only run when they are called. If you put your formatting on the downstream side (receiving a value and displaying it), everything will be reactive and all your values should display correctly. It will all just work whenever the source value changes. So do your formatting in a computed, like this...
js
computed: {
formattedPriceValue(){
return Number.parseFloat(this.priceValue).toFixed(2)
}
}
You can also just do it inline...
markup
<input type="number" :value="Number.parseFloat(priceValue).toFixed(2)">
The value you want to emit is probably the unformatted output of Number.parseFloat #change="$emit('price-changed', Number.parseFloat(event.target.value))"
Then, you will live longer if you do your number formatting with the Number functions provided.
Also, why don't you use the new template (multi-line) strings, delimited by a backtick `. They're much cleaner than the line continuation character you're using.
ps. I love seeing the chinese (?) comments in the code. I've copied and pasted them into my code. I hope there's no swearing. Unicode rocks.
I am trying to set the toolbar item dynamically. So far I have a back button that resets the toolbar title to 'start' if the user chooses to go back.
But the following code won't work:
menuList.on('itemtap', function(dataView, index, item, e){
viewport.dockedItems.items[0].setTitle('{title}');
});
It tries to use a variable called 'title' out of my data store array. This works great for providing text to my Ext.List items. But the above code sets the toolbar title to the string '{title}' without even thinking of it being a variable.
Can you help me out?
List's use templates so items within curley braces get evaluated... you'll need to pass a reference to a variable without quotes. You haven't provided enough code for me to tell you where that information would be. If you already have a variable in scope called title that you put the data into then you can just reamove the '{ and }' ... otherwise you'll need to get the data you need from your store through some means, like Ext.StoreMgr or [appname].stores
Two things. 1) You will really want to get used to digging into the ST source code. In this case, if you look at the code for "setTitle", you will see that its argument is interpreted as straight HTML, not a template. So you can't use curly bracket syntax here. 2) Note that the type of the "item" argument to the event handler is an Element (i.e. ST's representation of the DOM object, not the selected datastore object. So that's not going to help you. However, the "index" arg gives you an easy way to get the appropriate object from the store. i.e.
[appname].stores.pages.getAt(index).title
I really don't know why, but it works if you put up to variables: One for the record and one for the value inside that record. There is a detailed explanation in the sencha.com-forum