Why element.text() != element.#text? - testing

I'm new to Geb. I was trying to get text of html element. element.text() sometimes returns correct value, sometimes empty one. element.#text returns expected value.
Can someone explain this behaviour?

text() is for tag body and #text return the value of the text attribute

element.#text directly accesses the text attribute whereas text() calls a function to access the text, probably doing some stuff other than getting the attribute.
EDIT
According to the documentation, the text() method returns the text content for the first context element, which may be the reason why it sometimes doesn't return the value your are expecting (e.g. if you are looking for the text content for the second context element).
EDIT 2
For a NonEmptyNavigator, the implementation of the text() method looks like that:
#Override
String text() {
firstElement().text
}
For an EmptyNavigator, null is returned
#Override
String text() { null }
EDIT 3
As both Navigator implementations don't have a text attribute, the propertyMissing() method is called.
For implementation details, see here and here.

Related

Selenium webdriver: How to check an img element really have height attribute

in java Selenium web driver on chrome, I need to make sure that an image has a height attribute. The HTML code I have is this:
<img src="https://www.w3schools.com/tags/img_girl.jpg">
and I'm trying to execute
boolean s = driver.findElement(By.tagName("img")).getAttribute("height") !=null;
but this always returns true although there's no height attribute! and if I try to execute
String s = driver.findElement(By.tagName("img")).getAttribute("height");
I'll get 600 despite there is no height attribute in the HTML code. is there any other way I can check it?
Try this example:
#Test
public void testHeightAttribute(){
driver.get("https://webelement.click/en/welcome");
WebElement img = driver.findElement(By.xpath("//img[1]"));
System.out.println(img.findElements(By.xpath(".[#height]")).size());
System.out.println(img.findElements(By.xpath(".[#src]")).size());
}
I am not sure this is the most elegant way though :). The idea is that you're looking up elements using the element itself as a search context (looking up element within itself). If no attribute is present in DOM then the list would be empty (size() == 0). Otherwise it would be 1.
Basically the common method would look like:
public boolean hasAttributeInDom(WebElement element, String attr){
return !element.findElements(By.xpath(".[#" + attr + "]")).isEmpty();
}
You can check height parameter in styles section of Developer tools. Refer to attached screen shot of sample image from Stack overflow. You can see height parameter at right hand side. Generally, dimension are mentioned here.
You will need to understand and look for particular image property in Styles section as its display CSS properties for entire page.

Html.LabelFor not rendering HTML

I am binding a model to view.
public class Validation
{
[Display("Please enter in <h5>day(s)</h5>")]
public string Message { get; set; }
}
Here Message property will be set as Please enter in <h5>day(s)</h5>.
In view am binding model property to LabelFor.
#Html.LabelFor(m => m.Message)
Expecting output as
Please enter in day(s)
But actual output is
Please enter in <h5>day(s)</h5>
I want part of the string to vary in size and cosmetics, so applying CSS to the entire label is not what I'm looking for.
Your display string "<h5>some text</h5>" will be rendered as text, not HTML. MVC will encode the < > characters to < >, causing them to be displayed as-is.
You shouldn't want to do this like this anyway.
The proper way would be to apply the display string to contain the text you want:
[Display("some text")]
Then create a CSS class:
label.fancyLabel {
/* your style here that makes a label look like a h5 */
}
Then apply that class to the label (from .NET MVC - How to assign a class to Html.LabelFor?):
#Html.LabelFor(m => m.Message, new { #class= "fancyLabel" })
As for your edit, if you want to just render the Display attribute's text as literal HTML, you'll have to:
Introduce your own HTML helper.
In there, write a label (and make sure to set the for= attribute).
Read the DisplayAttribute's value.
#Html.Raw() that value as the label text.
Use #Html.YourLabelHelper(m => m.Message) to render it.
But using HTML on your models like that isn't really advisable. Views and templates should decide how to render a model, not the other way around.

Sitecore MVC Custom Link

I am trying to create a custom link from sitecore into my view
#Html.Sitecore().Field("CTA display", Model.Item, new { text = "<span>" + + "</span>"})
I am not 100% sure what the correct way to do this is, but I want to wrap the text from the link into a for styling. I've tried to put the Model.Rendering.Item.Fields["CTA display"] into there with .Text and it doesn't work.
Any help would be appreciated.
First, I'd start by creating a SitecoreHelper extension method that allows you to modify the inner html of the element you're rendering:
public static HtmlString Field(this SitecoreHelper helper, string fieldName, Item item, object parameters, string innerHtml)
{
if (helper == null)
{
throw new ArgumentNullException("helper");
}
if (innerHtml.IsNullOrEmpty())
{
return helper.Field(fieldName, item, parameters);
}
return new HtmlString(helper.BeginField(fieldName, item, parameters).ToString() + innerHtml + helper.EndField().ToString());
}
This will allow you to pass an optional innerHtml string that will be inserted between opening and closing tags of your element (in this case, an <a> tag).
From here, pass your html string containing your CTA label to the above method, or modify the method to output the field's Text value wrapped in a <span>.
I used the solution posted above by computerjules which worked a treat. You can then called the extended method like follows
#Html.Sitecore().Field("Link", Html.Sitecore().CurrentItem, new {Class = "some-class"}, "<span class='some-other-class'></span>")
and the span is rendered within the anchor tabs

how to hide dojo validation error tooltip?

I'm using dojo to validate input fields and if there is an error (for eg: required field) it appears in the dojo tooltip. But, I would like to show error in the custom div instead of tooltip.
So, I'm wondering if there is a way to hide/disable the validate error to appear in the tooltip? If so, I can capture the error message shown in the hidden tooltip and show the result in custom div, which will be consistent with error styling across the application.
Please advise. Thanks.
I would recommend to use the standard Dojo validation mechanism, contrary to what vivek_nk suggests. This mechanism works great in most cases, and covers most situations (required, regular expressions, numbers, dates etc.).
To solve your issue: you can overrule the "dispayMessage" function of a ValidationTextBox (for example).
displayMessage: function(/*String*/ message){
// summary:
// Overridable method to display validation errors/hints.
// By default uses a tooltip.
// tags:
// extension
if(message && this.focused){
Tooltip.show(message, this.domNode, this.tooltipPosition, !this.isLeftToRight());
}else{
Tooltip.hide(this.domNode);
}
}
Just create your own ValidationTextBox widget, extend dijit/form/ValidationTextBox, and implement your own "displayMessage" function.
Simple solution for this scenario is not to add the "required" condition at all to those fields. Instead add a separate event handler or function to check for this validation.
For eg: add a function for onBlur event. Check if the field is a mandatory. If so, show message in the custom div as expected.
<input data-dojo-type="dijit/form/TextBox"
id="sampleText" type="text" mandatory="true" onBlur="checkMandatory(this)"/>
function checkMandatory(field) {
if(field.mandatory=='true' && field.value=="") {
alert('value required'); // replace this code with my showing msg in div
} else {
field.domNode.blur();
}
}
This above code snippet does not use Dojo for validation, rather manual. Dojo actually helps to ease this by just adding the attribute "required". If that is not required, then just ignore Dojos help for this case and go native.
So, for all fields, just add the attributes - "mandatory" & "onBlur", and add the above given function for onBlur action for all these fields.

Selenium: Getting the value of elements in the dom when they are hidden

I am iterating a list of elements found ByClassName(). For each item in that list, I need to extract the text value of their child elements. I have seen some solutions for using javascript to get at the values, but I must be missing something. In this specific instance I have a span, and I need the text or innerhtml from it. I have verified with Firebug that there is text in it.
If all you want is to access the children elements you can also use xpath's //div[#class='Class']/child::div where you can change the classname and the child type. If you are wanting to access all children of the parent element you can return a list of elements that match your selector as below:
ReadOnlyCollection<IWebElement> elements = _driver.FindElements(By.XPath("//div[#class='ClassName']/child::div"));
At this point, yes, if you can access the element you should be able to access the innerHTML. Note that I have written my code in C#, which I believe is what your code is in too.
It turns out GetAttribute("innerHTML") is not inhibited by hidden html.
public string GetChildElementTextByClassName(IWebElement element, string className)
{
string returnValue = string.Empty;
try
{
IWebElement childElement = element.FindElement((By.ClassName(className)));
if (childElement != null)
{
returnValue = childElement.GetAttribute("innerHTML").Replace(Environment.NewLine, "").Trim();
}
}
catch (Exception)
{
//throw;
}
return returnValue;
}