Forum Discussion
The screenshot that your have provided,
What do the items look like in the Object Browser? What item does it reference in your web app? And what item(s) are you trying to find and click on, on the web app?
Also, what technology does you web application use? Is there a similar web app that I can use to test?
It's an Angular-based app. I just found a public sample page, where this can be tested:
https://material.angular.dev/components/chips/overview#autocomplete
I've updated the test project with this particular page and elements.
Basically, I need to find all mat-chip-rows and click [x] button for each row. Of course, I know there is an easy way to achieve this by using name mapping and simple loop. But I can't use it that way. This project is just a simplified sample. In original project, I'm collecting all form inputs (using the complicated xpath) and do various things for each input. Basically collecting IDs/values, storing them in JSON, eventually loading IDs/values from JSON and filling individual form inputs. Therefore, I'm working on a generic method, which should work with various forms, containing variable number and types of elements.
- rraghvani2 months ago
Champion Level 3
Not sure if this is helpful, but here's a few coding examples that highlights the button. Example 4 highlights and deletes. Name mappings are not used
function examples() { // Using Chrome, navigate to https://material.angular.dev/components/chips/examples var page = Sys.Browser("chrome").Page("https://material.angular.dev/components/chips/examples"); var panel = page.FindElement("//example-viewer[@id='chips-reactive-form']//chips-reactive-form-example/section/mat-form-field//mat-chip-grid[@role='grid']"); // Example 1 var items = panel.FindAll(["CustomObjectType", "contentText"], ["MatChipRow", "regexp:(how-to.*)"], 100); for (var i = 0; i < items.length; i++) { Sys.HighlightObject(items[i]); } // Example 2 var items = panel.FindAll(["CustomObjectType", "contentText"], ["MatChipRow", "tutorial*"], 100); for (var i = 0; i < items.length; i++) { Sys.HighlightObject(items[i]); } // Example 3 var items = panel.FindElements("//span[@aria-describedby='mat-mdc-chip-7-aria-description']|//span[@aria-describedby='mat-mdc-chip-4-aria-description']"); for (var i = 0; i < items.length; i++) { Sys.HighlightObject(items[i]); } // Example 4 var panel = page.FindElement("//app-component-viewer[contains(., 'overview')]") // Fina all objects in the page, where CustomObjectType = MatChipRow var items = panel.FindAll("CustomObjectType", "MatChipRow", 100); // Iterate through all found objects, highlight them and then click the X button to close them for (var i = 0; i < items.length; i++) { Sys.HighlightObject(items[i]); items[i].Button(0).Click(); } }
I also have this snippet of code,
function pagesize() { var page = Sys.Browser("chrome").Page("*"); page.contentDocument.Script.eval("document.body.style.transform='scale(0.8, 0.8)'"); aqUtils.Delay(2000); }
which performs JavaScript injections - which performs the same as if using Chrome DevTools. However, this functionality was last working in TC v15.55 and has been broken since.
- pkudrys2 months agoFrequent Contributor
Hi, thank you for the suggestions! Yeah, I will most probably have to use one of these workarounds. To be quite honest, I don't quite like them, because they add unnecessary complexity and hardcoded xpaths ;) I would still prefer to use aliasElement as the reference and fnid its parent or certain ancestor.
Do you know what's funny? As I mentioned before, FindElementByXPath failed to find the ancestor. You explained that TC uses an outdated JS, which may be the cause of this issue. However, I found out, that EvaluateXPath does exactly what's expected to do! It finds the expected ancestor element, which FindElementByXPath fails to find. The problem is, that it returns an object, which is again not compatible with FindElement and other find-related functions :D
As you can see here, the EvaluateXpath found proper element. But FindAll fails with "FindAll is not a function" error.
- eykxas2 months agoRegular Contributor
Hello!
I'm also working on an Angular project. For this type of project, I exclusively use XPath to retrieve my objects.
In your example, here's what I would do:
let ar = page.FindElements("//div[@role='presentation']//mat-chip-row"); //page is your parent object, this xpath returns an array of all the mat-chip-row inside your div.
- rraghvani2 months ago
Champion Level 3
There's a subtle difference between FindElement and FindElements, an easy mistake to miss!
pkudrys just want to reiterate, FindAll method will only work on those objects that appear in the Object Browser.
Standard methodsExtended methodsOtherwise, you will have to implement your own "FindAll" method. Which means finding the parent node first, and then iterating through each child node, any node that matches your criteria, you then save and append that node to an array - this is real programming, and you'll have total control of your search criteria!
- eykxas2 months agoRegular Contributor
I don't understand the issue here. He wants to get the list of all mat-chip-row and then doing something (click on the [X] button).
With FindElements (and the proper xpath) he gets an already populated array, and just need to iterate through.
That's what I'm doing in my projet, and it works fine. Without needing NameMapping.