How to make an assertion based on class name in web driver - webdriver

The HTML is as follows:
<section class="my-account-box-element">
<span class="item icon-home icon-color-1"></span>
</section>
Need to make an assertion based on the class name which changes from 'icon-home icon-color-1' to 'icon-home icon-color-0' depending upon the condition.

First i must warn that you can't add two classes when searching for it using the By, since 'item', 'item-home' on your example are the same. I'm going to assume the main difference is in 'item-color-1' and 'item-color-0'.
WebElement myAccountBoxElement = driver.findElement(By.className("my-account-box-element"));
WebElement spanItem = myAccountBoxElement.findElement(By.tagName("span"));
boolean itemColor = (spanItem.getAttribute("class").contains("item-color-1")) ? true : false;
if (itemColor) {
// do stuff for item-color-1 element
}
// do stuff for the item-color-0 element
}
The above code should work flawlessly provided the above code is the actual HTML, if there are more tags, use findElements() instead and loop in it.
Also i went with a ternary if since it keeps a cleaner code, providing you are only working with those two elements

change as per your needs
assertTrue(driver.findElements( By.Xpath(".//span[contains(#class,'icon-color-1')]")).size() != 0)

Can also use this
By.className("classname");
boolean isElementPresent = driver.findElement(By.className("classname"));

Related

Aurelia not displaying correct representation of array after removing item

I have a list of items in an array.
When i click the item in my view i am attempting to remove this item
View
<div class="lootItem" repeat.for="lootItem of stack">
<div class="noselect" click.delegate="$parent.takeItem(lootItem)">
<i class="fa fa-diamond"></i> ${lootItem.value}
</div>
</div>
ViewModel
takeItem(lootItem){
this.eventAggregator.publish(new ItemTaken(lootItem));
console.log(_.includes(this.stack, lootItem)); //true
_.pull(this.stack, lootItem); //removes item and fails to update the ui
_.remove(this.stack, lootItem); //removes item and fails to update the ui
this.stack.shift(); //removes first item and updates the ui
}
Both .pull() and .remove() (using lodash) will remove the item in the array but not update the ui.
.shift() manages to remove an item from the array and is updating the UI.
Why is Aurelia not updating the UI despite me removing the item when using lodash?
addendum: it might be worth noting if i click the same item twice then _.includes is true the first time and then false the second time.
Aurelia can provide you with the index of the current item when inside a repeater using the $index variable. Then, simply use the built in array methods that ES2015 provides:
View
<div class="lootItem" repeat.for="lootItem of stack">
<div class="noselect" click.delegate="$parent.takeItem($index, lootItem)">
<i class="fa fa-diamond"></i> ${lootItem.value}
</div>
</div>
ViewModel
takeItem($index, lootItem){
this.eventAggregator.publish(new ItemTaken(lootItem));
this.stack.splice($index, 1);
}
I believe your problem lies in the scope of the variables.
_.pull and _.remove are returning a new instance of an array.
Try
this.stack = _.remove(this.stack, lootItem);
Using ES2015 Sets Yet another approach is to use the ES2015 Set data
structure. It can be initialized with an array of values, and the Set
prototype even provides a delete method for removing a specific value
...
However, the semantics of sets are different from regular arrays. By
definition, a set is a collection of unique values. Therefore, it
never contains duplicates. If you need a collection that allows for
duplicate values, sets are the wrong data structure.
https://blog.mariusschulz.com/2016/07/16/removing-elements-from-javascript-arrays
I am now using a Set for this and it allows me to use .add() and .delete(). I just need to remember that everything has to be unique (okay in my case here)
I'd still like to understand why manipulating the array though lodash doesn't work but i'll investigate that some other time.
Addendum
You can also use a prototype:
interface Array<T> {
remove(itemToRemove: T): Array<T>;
}
(<any>Array.prototype).remove = function (itemToRemove) {
const index = this.indexOf(itemToRemove);
if (index !== -1) {
this.splice(index, 1);
}
return this;
}

Using Google Sites and Google App Scripts, how can I dynamically change the CSS class of an HTML element?

I am using Google Sites for my webpage and I want parts of it to be kind of dynamic. Hence, what I want to achieve is to change the CSS class associated with certain HTML element in the presence of an on click event.
E.g.:
Initial situation:
<div class="foo">Hello</div>
World
After clicking on "World":
<div class="bar">Hello</div>
World
Add an ID to the div, then:
function method() {
var myDiv = document.getElementById("myDIV");
myDiv.className = "bar";
}
Alternatively you can get all elements with that particular class name, then loop through them to change their class name.
function method() {
var myDivs = document.getElementsByClassName("foo");
for (var i = 0; i < myDivs.length; i++)
myDivs[i].className = "bar";
}
Now of course you can add if/else statements to check for certain conditions before making changes.
Now that I understand what you are looking for, Check this link.
There is a get and set method for the HTML content of the page requested. By manipulating the generated string, it should be possible to then change the div to the required class and other such things. This should be a good start, we'll have to play around with the rest.
This might also be helpful, but I believe it has several limitations.

Is there a way to filter out hidden elements with css?

as an example some html has several elements which have the css path table.class1.class2[role="menu"] but only one of these elements will be visible at any given time, so I want to get only the one that is visible.
can I adjust my css path to narrow it down?
Possibly use Linq to get the list. I am not sure which language you are using. But, similar concept can be applied using any of them. Using Linq
to accomplish this kind of scenario is very simple in C#
public IWebElement Test()
{
//selector
By bycss = By.CssSelector("table.class1.class2[role='menu']");
return Driver.FindElements(bycss).ToList().FirstOrDefault(d => d.Displayed);
}
And, make sure to import
using System.Linq; if you are using C#
In Java you can do something like this[not using lambdas]
List<WebElement> visibleList = null;
//selector
By byCss = By.cssSelector("table.class1.class2[role='menu']");
//list of visible and hidden elements
Iterator<WebElement> iterator = driver.findElements(byCss).iterator();
while (iterator.hasNext()){
WebElement element = iterator.next();
if (element.isDisplayed()){
//building the list of visible elements
visibleList.add(element);
}
}
//get the first item of the list
//you can return all if needed
return visibleList.get(0);
In Java, you can use WebElement.isDisplayed().

click() on css Selector not working in Selenium webdriver

HTML
<input class="button" type="button" onclick="$.reload('results')" value="Search">
I don't have an id or name for this . Hence am writing
FirefoxDriver driver = new FirefoxDriver();
driver.get("http://....");
driver.findElement(By.cssSelector("input[value=Search]")).click();
But click() is not happening.
Tried
driver.findElement(By.cssSelector(".button[value=Search]")).click();
Tried
value='Search' (single quotes).
these Selectors are working in
.button[value=Search] {
padding: 10px;
}
input[value=Search] {
padding: 10px;
}
i would inject piece of js to be confident in resolving this issue:
first of all locate element using DOM (verify in firebug):
public void jsClick(){
JavascriptExecutor js = (JavascriptExecutor) driver;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("document.getElementsByTagName('button')[0].click();");
js.executeScript(stringBuilder.toString());
}
jsClick();
from the retrospective of your element it be like:
....
stringBuilder.append("document.getElementsByTagName('input')[0].click();");
....
Please, note: document.getElementsByTagName('input') returns you an array of DOM elements. And indexing it properly e.g. document.getElementsByTagName('input')[0], document.getElementsByTagName('input')1, document.getElementsByTagName('input')[2]....
,etc you will be able to locate your element.
Hope this helps you.
Regards.
Please use the below code.
driver.findElement(By.cssSelector("input[value=\"Search\"]")).click();
It works for me. And make sure that the name is "Search", coz it is case sensitive.
Thanks
Are you sure that using this CSS-selector (input[value=Search]) on your page you have only one result?
single quotes are missing in your code, the [value=Search] should be replaced with [value='Search'].
first you have to check if the selector u are using will work or not..
If you are using chrome or FF,you can follow these steps,
go to the page where button (to be clicked) is present,
open web console and type in the following and click enter..
$("input[value='Search']")
or
$("input[value='Search'][type='button']")
or
$("input[value='Search'][type='button'].button")
you will get a list of elements which can be accessed using this selector, if that list contains only one element (button that you want to click), then this selector is valid for your use..otherwise u'l have to try some other selector..
If any of the above selector is valid,u'l have to change your code accordingly..
driver.findElement(By.cssSelector("input[value='Search'][type='button'].button")).click();

Removing all elements from HTML that have given class using Agility Pack

I'm trying to select all elements that have a given class and remove them from a HTML string.
This is what I have so far it doesn't seem to remove anything although the source shows clearly 4 elements with that class name.
// Filter page HTML to display required content
HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
// filePath is a path to a file containing the html
htmlDoc.LoadHtml(pageHTML);
// ParseErrors is an ArrayList containing any errors from the Load statement);
if (!htmlDoc.ParseErrors.Any())
{
// Remove all elements marked with pdf-ignore class
HtmlNodeCollection nodes = htmlDoc.DocumentNode.SelectNodes("//body[#class='pdf-ignore']");
// Remove the collection from above
foreach (var node in nodes)
{
node.Remove();
}
}
EDIT: Just to clarify the document is parsing and the SelectNodes line is being hit, just not returning anything.
Here is a snippet of the html:
<input type=\"submit\" name=\"ctl00$MainContent$PrintBtn\" value=\"Print Shotlist\" onclick=\"window.print();\" id=\"MainContent_PrintBtn\" class=\"pdf-ignore\">
EDIT: in your updated answer you posted a part of the HTML string an <input> element declaration, but you're trying to match a <body> element with the class pdf-ignore (according to your expression //body[#class='pdf-ignore']).
If you want to match all the elements from the document with this class you should use:
var nodes = htmlDoc.DocumentNode.SelectNodes("//*[contains(#class,'pdf-ignore')]");
code to get your nodes. This will match all the elements with the class name specified.
Your code is seems to be correct except the one detail: the condition htmlDoc.ParseErrors == null. You select and remove nodes ONLY if the ParseErrors property (which is a type of IEnumerable<HtmlParseError>) is null, but actually if no errors found this property returns an empty list. So changing your code to:
if (!htmlDoc.ParseErrors.Any())
{
// some logic here
}
should solve the issue.
Your xpath is probably not matching: have you tried "//div[class='pdf-ignore']" (no "#")?

Resources