Playwright c# how to select one of multiple identical elements - playwright

Im using playwright with C# and a trying to do the following:
I have two elements with the same locator.
I want to be able to locate one of them by position, i.e 1st or 2nd found.
when do the following:
var nameField = page.Locator("div[data-key='Name']");
await nameField.FillAsync("");
I get the error:
Microsoft.Playwright.PlaywrightException : Error: strict mode violation: "div[data-ph-key='Name']" resolved to 2 elements:
Ive tried the following based on the playwright documentation:
var nameField = page.Locator("div[data-ph-key='Name'] >> nth=0");
this results in the element resolved to 2 elements error:
also tried this
var nameField = page.Locator("div[data-key='Name']");
await nameField.First.FillAsync("");
which returns the same error
How can do a simple select the nth element found and interact with it?
Is there something similar to selenium's IWebelements where I would put all the matching elements in a collection and interact with the desired one based on its index position?

Okay, so this works:
var nameField = page.Locator("div[data-key='Name']")
await nameField.Nth(0).FillAsync("");

Related

How to bind an entity object on a Detail page

I am developing a master detail Fiori app using SAP UI5. As the details contains more than 40 columns, I made separate OData services for master & detail.
In Master page, data are coming correctly. Now my task is that on any table line, when user clicks on Detail, next page will be open with details base on two key values of master table.
I'm getting two keys in variables in detail page as follows and it is working fine:
var spayid = jQuery.sap.getUriParameters().get("payid");
var spaydt = jQuery.sap.getUriParameters().get("paydt");
Next, I have created two filters as follows which is also working fine.
var filter1 = new Filter({
path: "Laufi",
operator: FilterOperator.EQ,
value1: spayid
});
var filter2 = new Filter({
path: "Laufd",
operator: FilterOperator.EQ,
value1: spaydt
});
Now I am calling OData service which is also working fine:
var oODataModel = new ODataModel("proxy/http/FIORI-DEV.abc.com:8000/sap/opu/odata/sap/ZASA_FI_pay_D_SRV?sap-client=100", {
json: true,
useBatch: false
});
this.getView().setModel(oODataModel);
I don't know now how to filter data. What should be included in above so that it will filter data according to my filters filer1 and filter2? I have tried following but it is not working.
filters : [ filter1, filter2 ],
json: true,
useBatch: false
I am very good in ABAP but not an expert in SAPUI5. I am in learning phase.
First of all, I was thinking to pass parameters on OData service so that only the required data are fetched. Means my OData call should be like this:
new ODataModel("proxy/http/FIORI-DEV.abc.com:8000/sap/opu/odata/sap/ZASA_FI_PAYMENT_D_SRV/PdetailSet(Laufi= spayid, Laufd = spaydt)?sap-client=100");
But this seems not like possible.
Second option is that I will fetch whole details in OData service and then during binding to table I will apply filter.
The purpose of the sap.ui.model.Filter class is usually to apply filters to lists on the UI. For example, if you have a list of items and you want to limit that list to a subset of items which fulfills certain criteria.
But what you have here appears to be a classic master-detail scenario where you have a list of items and then when the user selects one show more information about that one item.
The usual solution for such a scenario is to assign the full model to the detail-view and then use an element binding (also known as "context binding") on the view to tell it which item to display.
When the source of the item is a click on an element which already had an element binding, then you can actually retrieve the correct binding path from the click event and just apply it to your detail-view.
From one of the official demos:
onItemSelected: function(oEvent) {
var oSelectedItem = oEvent.getSource();
var oContext = oSelectedItem.getBindingContext("products");
var sPath = oContext.getPath();
var oProductDetailPanel = this.byId("productDetailsPanel");
oProductDetailPanel.bindElement({ path: sPath, model: "products" });
}
When you don't have any convenient way to get an element path from, then you have to construct one yourself:
var detailPanel = this.getView().byId("idOfDetailPanel");
detailPanel.bindElement("PdetailSet(Laufi = " + spayid +", Laufd = " + spaydt + ")");
The latter code snippet does of course assume that the oData-service actually supports access with a key consisting of laufi and laufd. This is decided by:
The definition of the key fields of the entity type in the SAP Gateway Service Builder (transaction SEGW)
The ABAP implementation of the method get_entity of the data provider class of that oData-service.

How to get list of child elements of an element in Appium?

I'm working with native iOS app through Appium.
I have the following structure:
UIAApplication ->
UIAWindow ->
UIATextBox
UIALabel
UIAWindow ->
SomethingElse
I have found a way to get the first UIAWindow and I'd like to get the list of all elements in that window. How do I do that?
I'd like to get UIATextBox and UIALabel from first UIAWindow but NOT SomethingElse element.
How do I do list of child elements in general?
#Test
public void testListWindows() {
List<MobileElement> windows = driver.findElementsByClassName("UIAWindow");
List<MobileElement> elements = windows.get(0).?????
}
You're almost there. What you have is giving you a list of all UIAWindows when what you want is a list of all the elements of the first UIAWindow. I'd suggest using Xpath with a wildcard.
This will get you every element that is a direct child of the first UIAWindow:
List<MobileElement> elements = driver.findElements(MobileBy.xpath("//UIAWindow[1]/*");
And this will get you every child and sub-child and sub-sub-child etc. of the first UIAWindow:
List<MobileElement> elements = driver.findElements(MobileBy.xpath("//UIAWindow[1]//*");
An extra tip: If you're automating for iOS, I assume that means you have access to OS X, where you can install the Appium dot app and use inspector. The inspector is a great tool to test out xpath queries before putting them into your code.
You can also find textfield and label by its class for iOS app in Appium. findElementsByClassName method will return all elements on current screen that matches that class.
List<MobileElement> textFields = driver.findElementsByClassName("UIATextField");
MobileElement textField = textFields.get(0);
List<MobileElement> labels = driver.findElementsByClassName("UIAStaticText");
MobileElement label = labels.get(0);

running UIAutomation script in many macs?

I could create and replay the following script very well in the mac I Use.
var target = UIATarget.localTarget();
UIATarget.localTarget().delay(15);
target.frontMostApp().mainWindow().tableViews()[0].textFields()[0].tap();
When I run the above script in another mac, It shows error in the 3rd line.
after changing the above script's third line as following, it is replaying fine.
target.frontMostApp().mainWindow().tableViews()[1].textFields()[0].tap();
Just I have changed tableview's index from 0 to 1. How can I achieve this in multiple
mac systems? Both mac are having same xcode version(xcode 5) and simulator version(6.1) and mac version.Why Instruments are taking scripts API differently in different macs?
For more consistent results one of the ways can be to access AX element by name (or other identifier/expected content/number of contained cells etc.). For example here Trouble Getting Elements by Name from UIAElementArray in UIAutomation SO question and corresponding discussion about how name for element can be set in different ways.
For example:
var mainWindow = UIATarget.localTarget().frontMostApp().mainWindow();
var tableViews = mainWindow.tableViews();
tableViews['TableView'].textFields()[0].tap();
or
var mainWindow = UIATarget.localTarget().frontMostApp().mainWindow();
var tableViews = mainWindow.tableViews();
tableViews['TableView'].textFields.withName("TextFieldName")[0].tap();
If using names are not practicable can be analysed content of the table and according to that right table can be selected. For example if table has some cell with name "Cell name":
var mainWindow = UIATarget.localTarget().frontMostApp().mainWindow();
var tableViews = mainWindow.tableViews();
if (tableViews[0].cells().firstWithName("Cell name")) {
tableViews[0].textFields()[0].tap();
} else if (tableViews[1].cells().firstWithName("Cell name")) {
tableViews[1].textFields()[0].tap();
}
More details about identifying cells in tableView for example in SO question UIACollectionView cells vs visibleCells This looks not very nice but it can be reasonable workaround and should work quite reliable. If number of cells are know and different in these tables than number of cells can be compared to find required table.

Monodroid screen dimensions

I'm trying to reference WindowManger so I can get the default screen's dimensions but I can't seem to find reference to it. (this is API 8, froyo 2.2). I even tried:
dynamic wm = Android.App.Application.Context.GetSystemService(Android.Content.Context.WindowService);
Display display = wm.getDefaultDisplay();
But got an error indicating that Object doesn't respond to getDefaultDisplay.
Also I tried:
var wm = (IWindowManager)Android.App.Application.Context.GetSystemService(Android.Content.Context.WindowService);
Display display = wm.DefaultDisplay;
But I get an invalid cast exception.
Saw this post, but I can't resolve WindowManager. Any ideas what's going on here?
WindowManager is the IWindowManager interface. Instead of the cast, try using the .JavaCast<T>() extension method:
var wm = context.GetSystemService(Android.Content.Context.WindowService)
.JavaCast<IWindowManager>();
var d = wm.DefaultDisplay;
You can also check out the AccelerometerPlay sample.
Another simpler way is
Display display = this.WindowManager.DefaultDisplay;
You can get the Width and Height properties from the display object.
using Android.Runtime; //for JavaCast
var windowManager = Android.App.Application.Context.GetSystemService(Android.Content.Context.WindowService).JavaCast<IWindowManager>();

Dynamic Linq/ Dynamic Query: cannot get data for jqGrid

I'm using jqGrid and I have a problem getting Dynamic Linq to work. I used NuGet to install Dynamic and added "using System.Linq.Dynamic;".
Using VS 2010 Pro, MVC 3.0
This works:
var s = context.testdata;
var c = s.Count();
c shows 5136 items.
But I cannot get the dynamic approach to work:
var s = context.testdata.OrderBy("id asc");
I get this error message:
'id' could not be resolved in the current scope or context.
Make sure that all referenced variables are in scope,
that required schemas are loaded, and that namespaces are referenced correctly.
This however does work:
var s = (from ss in context.testdata
orderby ss.id
select ss).ToList();
var c = s.Count();
Again I get all 5136 items.
I've got the code from here:
http://haacked.com/archive/2009/04/14/using-jquery-grid-with-asp.net-mvc.aspx
and here:
http://www.timdavis.com.au/code/jquery-grid-with-asp-net-mvc/
Any idea what I am doing wrong?
OK, found the solution here:
Strange Exception thrown using Dynamic Linq Entity Framework Query
This works:
var s = context.testdata.OrderBy("it.id asc");

Resources