Selenide combines 2 ElementsCollections - selenium

I have 2 ElementsCollections namely oddTableRowItems and evenTableRowItems:
private static ElementsCollection oddTableRowItems() {
return $$(By.className("odd"));
}
private static ElementsCollection evenTableRowItems() {
return $$(By.className("even"));
}
I want to combine the 2 in order to only do a for loop once. It is row items, and only there classnames differ for styling purposes and I can only identify them through classnames.
This is how I tried to combine it - but it does not work:
ElementsCollection rowElements = evenTableRowItems();
rowElements.addAll(oddTableRowItems());
I get an:
java.lang.UnsupportedOperationException
does anybody how can I combine the 2 ElementsCollections?

The API could probably be a little bit more friendly here. But this way you can combine two ElementsCollection instances. The key here is WebElementsCollectionWrapper class.
ElementsCollection evenElements = $$(By.className("even"));
ElementsCollection oddElements = $$(By.className("odd"));
List<SelenideElement> elementsCombined = new ArrayList<>(evenElement);
elementsCombined.addAll(oddElements);
WebElementsCollectionWrapper wrapper = new WebElementsCollectionWrapper(elementsCombined);
ElementsCollection selenideCollectionCombined = new ElementsCollection(wrapper);

All add* methods throw UnsupportedOperationException by design. It's because ElementsCollections represents a collection of existing web elements on a web page; and page elements cannot be modified by test. That's why you cannot add or remove elements on the page.
The easiest way is to select all matching elements at once:
$$(".odd,.even").shouldHave(size(10));
A little bit longer way is to compose a new list containing both collections:
List<String> newList = new ArrayList<String>();
newList.addAll($$(".odd"));
newList.addAll($$(".even"));
but your goal seems to be doubtful for me. You will get the list with invalid order. Why can it be useful? Why would one need to iterate all elements? I cannot imagine a use case for that.

According to the API:
Note that this implementation throws an UnsupportedOperationException unless add(int, E) is overridden.

You can try this code. This is work fine!
ArrayList<SelenideElement> newList = new ArrayList<SelenideElement>();
newList.addAll(Selenide.$$(By.className("odd"));
newList.addAll(Selenide.$$(By.className("even"));

Related

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

How to customize the labels of an Infragistics Ultrachart?

I am trying to customize the series labels of the X axis of a linear ultrachart using vb.net.
I looked into the documentation from Infragistics and found that I could use this code:
UltraChart.Axis.Y.Labels.SeriesLabels.FormatString = "<Item_Label>"
A description of the types of labels available can be seen here.
However, I'm not getting the result I expected. I get "Row#1" and I want to get only the "1".
I've tried the approach used in the first reply of this post in Infragistics forums, which consists of using an hashtable with the customized labels. The code used there is the following (in C#):
Hashtable labelHash = new Hashtable();
labelHash.Add("CUSTOM", new MyLabelRenderer());
ultraChart1.LabelHash = labelHash;
xAxis.Labels.ItemFormatString = "<CUSTOM>";
public class MyLabelRenderer : IRenderLabel
{
public string ToString(Hashtable context)
{
string label = (string)context["ITEM_LABEL"];
int row = (int)context["DATA_ROW"];
int col = (int)context["DATA_COLUMN"];
//use row, col, current label's text or other info inside the context to get the axis label.
//the string returned here will replace the current label.
return label;
}
}
This approach didn't work either.
I am using Infragistics NetAdvantage 2011.1.
Anyone has any idea how to customize these labels in order to obtain the number after "Row#"?
There are different approaches to solve this task. One possible solution could be if you are using FillSceneGraph event. By this way you could get your TEXT primitives and modify it. For example:
private void ultraChart1_FillSceneGraph(object sender, Infragistics.UltraChart.Shared.Events.FillSceneGraphEventArgs e)
{
foreach (Primitive pr in e.SceneGraph)
{
if (pr is Text &&((Text)pr).labelStyle.Orientation == TextOrientation.VerticalLeftFacing )
{
pr.PE.Fill = Color.Red;
((Text)pr).SetTextString("My custom labels");
}
}
}
OK. I`ll try to explain more deeply about FormatString property.
When you are using this property, you could determinate which information to be shown (for example: Items values or Data Values or Series Values). Of course there are option to use your custom FormatString.
For example:
axisX2.Labels.ItemFormat=AxisItemLabelFormat.Custom;
axisX2.Labels.ItemFormatString ="";
In this case we have labels which represent Date on your X axis, so if you are using these two properties, you are able to determinate the Date format (for example dd/MM/yyyy or MM/ddd/yy). In your scenario you have string values on your X axis. If you are not able to modify these strings values at lower level (for example in your database, through TableAdapters SQL query, DataSet, i.e. before to set your DataSource to our UltraChart), then you could use FillSceneGraph event and modify your Text primitives. More details about this event you could find at http://help.infragistics.com/Help/NetAdvantage/WinForms/2013.1/CLR4.0/html/Chart_Modify_Scene_Graph_Using_FillSceneGraph_Event.html If you need a sample or additional assistance, please do not hesitate to create a new forum thread in our web site - http://www.infragistics.com/community/forums/
I`ll be glad to help you.

Angular dynamic factory

I'm trying to use a single controller to list multiple similar collections so I can call different templates with the same controller. In fact, right now I have 6 controllers for listing and another 6 for forms but they're all duplicates.
I've made a non-functional plunker just to show how I intend it to work. I've avoided declaring routeProviders because knowing it wouldn't work I tried to make it as straight to the point as I could.
http://plnkr.co/edit/d06PcrJS5newhrmNy6EJ?p=preview
I've seen on stackoverflow how to declare a class with a dynamic name:
var str = "MyClass";
var obj = new window[str];
But as I have not been able to find where it's stored I'm not able to retrieve it.
Does anyone have a hint on how to do this?
You can use Angular's injector to return the service instance you want. For example:
app.controller('NodeListCtrl', function($scope, $location, $injector) {
var modelName = $location.path().split("/")[1];
$scope.modelName = modelName.charAt(0).toUpperCase() + modelName.slice(1);
$scope.nodes = $injector.get($scope.modelName).query();
});
Note: Don't forget to add the $injector to the controller's function signature.
jsfiddle: http://jsfiddle.net/bmleite/Mvk2y/

Raven DB: How can I delete all documents of a given type

More specifically in Raven DB, I want to create a generic method with a signature like;
public void Clear<T>() {...
Then have Raven DB clear all documents of the given type.
I understand from other posts by Ayende to similar questions that you'd need an index in place to do this as a batch.
I think this would involve creating an index that maps each document type - this seems like a lot of work.
Does anyone know an efficient way of creating a method like the above that will do a set delete directly in the database?
I assume you want to do this from the .NET client. If so, use the standard DocumentsByEntityName index:
var indexQuery = new IndexQuery { Query = "Tag:" + collectionName };
session.Advanced.DocumentStore.DatabaseCommands.DeleteByIndex(
"Raven/DocumentsByEntityName",
indexQuery,
new BulkOperationOptions { AllowStale = true });
var hilo = session.Advanced.DocumentStore.DatabaseCommands.Get("Raven/H‌​ilo/", collectionName);
if (hilo != null) {
session.Advanced.DocumentStore.DatabaseCommands.Delete(hilo.‌​Key, hilo.Etag);
}
Where collectionName is the actual name of your collection.
The first operation deletes the items. The second deletes the HiLo file.
Also check out the official documentation - How to delete or update documents using index.
After much experimentation I found the answer to be quite simple, although far from obvious;
public void Clear<T>()
{
session.Advanced.DocumentStore.DatabaseCommands.PutIndex(indexName, new IndexDefinitionBuilder<T>
{
Map = documents => documents.Select(entity => new {})
});
session.Advanced.DatabaseCommands.DeleteByIndex(indexName, new IndexQuery());
}
Of course you almost certainly wouldn't define your index and do your delete in one go, I've put this as a single method for the sake of brevity.
My own implementation defines the indexes on application start as recommended by the documentation.
If you wanted to use this approach to actually index a property of T then you would need to constrain T. For example if I have an IEntity that all my document classes inherit from and this class specifies a property Id. Then a 'where T : IEntity' would allow you to use that property in the index.
It's been said in other places, but it's also worth noting that once you define a static index Raven will probably use it, this can cause your queries to seemingly not return data that you've inserted:
RavenDB Saving to disk query
I had this problem as well and this is the solution that worked for me. I'm only working in a test project, so this might be slow for a bigger db, but Ryan's answer didn't work for me.
public static void ClearDocuments<T>(this IDocumentSession session)
{
var objects = session.Query<T>().ToList();
while (objects.Any())
{
foreach (var obj in objects)
{
session.Delete(obj);
}
session.SaveChanges();
objects = session.Query<T>().ToList();
}
}
You can do that using:
http://blog.orangelightning.co.uk/?p=105

cellBrowser placed in composite - do I have to attach directly to the rootpanel (or rootlayoutpanel)

when using a cellbrowser and adding that widget to a flowpanel (to be placed wherever, downstream), for some reason the end result is dead (a blank screen)...vs if I add directly to the rootpanel (or layout panel)
Also had the same problem. I had to use a <g:HTMLPanel> as the parent of the CellBrowser (as seen in the GWT Showcase).
Do you have some sample code that will reproduce this?
below is the code for the composite...essentially, what I'd like to do is in another class, attached this composite to a flowpanel and do whatever with it...but, the reality is, I have to attach is directly to the RootPanel (or RootLayoutPanel)...any other abstraction causes it to bail
for example
FlowPanel fp = new FlowPanel();
V2_M76Rolodex v = new V2_M76Rolodex();
fp.add(v); // not going to work
RootPanel.get.add(v) works
public class V2_M76Rolodex extends Composite {
/*
a bunch of code here for getting data and
populating the tree - works, not at issue or relevant
*/
public V2_M76Rolodex() {
TreeViewModel model = new CustomTreeModel();
CellBrowser browser = new CellBrowser(model, null);
browser.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
browser.addStyleName("rolodex_cell_browser");
initWidget(browser);
}
}