Could not access element by ID - c#

I am facing with problem when I tried to access Android element by ID in C#, I also tried with Appium-desktop version and seems not accessible for example:
I tried with and without package name and there is an exception every time which says could not find element. Also from Appium desktop selector.
AndroidElement selectPlant = driver.FindElementById("com.heidelbergcement.aom.stage.dev:id/loginForm-plantSelection")

You're misunderstanding something.
FindElementById refers to the unique identifier of the element which in most cases is the RuntimeId of the UI element.
What you should use is findElementByAccessibilityId, which refers to AutomationId of the UI element as shown in the inspect tool.
Total credit to this.

Related

How to set level of newly placed FamilyInstance?

I'm placing a new face-based family instance into my Revit model with the help of the NewFamilyInstance Method (Face, XYZ, XYZ, FamilySymbol) method described here. This works fine, except the instance does not have its level set to that of the host (it's set to -1 when accessed through the API and just left blank in the UI).
I tried setting the level like such
placedInstance.LevelId = hostWall.LevelId
and following this approach also tried
placedInstance.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM).Set(hostWall.LevelId);
but both throw an error saying the parameter is readonly.
Any help would be appreciated!
On some elements, the element level can only be set during the creation of the element. For that, I would assume that you need to use a different overload of the NewFamilyInstance method. Please refer to this explanation by The Building Coder and a few recent discussions of related topics in the Revit API discussion forum:
Change level of existing element
LevelId is null
Change level on line based family

Problem selecting attribute using XPath in Selenium .NET Core Project

I have a curious issue for which I can not seem to find a solution on this forum (or elsewhere on the internet)
I am building a test automation application using Selenium and .NET Core 3.1. I am trying to select an element in the DOM using a OpenQA.Selenium.IWebDriver and previously selected OpenQA.Selenium.IWebElement and an Xpath selector like so:
IWebElement parent => driver.FindElement(By.CssSelector("#parent"));
IWebElement child(string t) = parent.FindElement(By.XPath($".//li[#data-original-title=\"{t}\"]"))
...
var el = child("'title-1'");
Where the DOM is the following:
<div id="parent">
... <!-- child element is nested multiple levels -->
<li title data-original-title="'title-1'"></li>
<li title data-original-title="'title-2'"></li>
...
</div>
When I try to perform this action i get the following error:
OpenQA.Selenium.NoSuchElementException : no such element: Unable to locate element: {"method":"xpath","selector":".//li[#data-original-title="'title-1'"]"}
(Session info: chrome=85.0.4183.102)
However when I copy this xpath which is apparently non existent and search the dom using chrome debugger it does match the element.
Then I tried to figure out what could be the cause, maybe I made a mistake with the parent or smth. So I try the following XPath for the child selector, matching the other attribute (with out value)
IWebElement child(string t) = parent.FindElement(By.XPath($".//li[#title]"))
This does return an element, and after checking the debugger it is my intended child element. Now I assume something must go wrong with the formatting of the string so I try the following selector (without the value)
IWebElement child(string t) = parent.FindElement(By.XPath($".//li[#data-original-title]"))
This produces (roughly) the same error as before:
OpenQA.Selenium.NoSuchElementException : no such element: Unable to locate element: {"method":"xpath","selector":".//li[#data-original-title]"}
(Session info: chrome=85.0.4183.102)
And again when I try to find the element in the DOM using the search function in the chrome debugger using the above xpath .//li[#data-original-title] it does match my expected child element.
So I am now thinking the hyphens must cause the problem. I tried some research on the issue but the only real thing I could find was this stackoverflow article
Here they recommend to use an CSS selector instead, which I tried and also did not work, furthermore I believe the relative to parent function does not work with the CSS selector.
In this article the poster comments that the problem in the end was caused by DOM structure, which does not help me very much and also makes me think I just made a big mistake somewhere along the line that I just have been overlooking.
Conclusion
Based on the above XPath selector is there anything I have done wrong that causes my mismatch, or is there maybe a difference in implementation of XPath in chrome debugger vs the .NET Core Selenium library that I should know of that could cause this issue?
Thanks in advance and sorry for the long post :$
So as it turned out it was something I overlooked. The data-original-tile attribute is set reactively, based on user mouse input (as it is used for conditionally displaying a tooltip) and title property is cleared. Since selenium only fires a click event and does not actually hover above the element without specifically clarifying so the attributes won't be swapped during automation.
Conclusion
I should have checked the source HTML more thoroughly for updates to the DOM on user interaction.

selenium c# - "lazy" driver.FindElements(By..)

In my effort of trying to find a neat way to validate which buttons are visible to the user based on his Role and Permissions i have encountered a problem. I am using the Page Object Model design pattern with selenium to test a website. A few pages have a different set of buttons which should either be visible or not to the user according to his role.
I keep a Dictionary<Permission,IWebElement> and initialize it in the constructor of the page (class representing a certain page in the site).
All web elements are defined as follows:
private IWebElement btn_openShop => driver.ById("open_shop");
(ById is equivalent to FindsElement(By.Id("open_shop"))
The problem is that if the button shouldn't exist an exception is thrown when adding it to the Dictionary.
Note: moving the initialization of the Dictionary wont help since i test both cases (one in which the user should see the button and one in which he shouldn't).
I changed the Dictionary to be of type <Permission,Lazy<IWebElement>>
and added items to it as follows:
dictionary.Add(somePermission,new Lazy<IWebElement>(()=>the button))
Edit: this technique works but it seems that when debugging in visual studio the code crashes.
Any thoughts? (no exceptions are thrown during test execution).

Unable to locate element using UIAutomation

I am using the UIAutomation library from Microsoft for C#. I have an element with the following properties:
LocalizedControlType: "edit"
AutomationId: "Database"
Readonly: False
Text field
I am able to read these properties using Inspect. However, I am unable to find it with the following command in C#:
AutomationElement ae = root.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "Database"), new PropertyCondition(AutomationElement.LocalizedControlTypeProperty, "edit"));
In fact, the only way I can find it is via the following command (which follows the tree):
AutomationElement ae = root.FindAll(TreeScope.Children, Condition.TrueCondition)[0]
.FindAll(TreeScope.Children, Condition.TrueCondition)[0]
.FindAll(TreeScope.Children, Condition.TrueCondition)[0]
.FindAll(TreeScope.Children, Condition.TrueCondition)[0]
.FindAll(TreeScope.Children, Condition.TrueCondition)[2]
.FindAll(TreeScope.Children, Condition.TrueCondition)[0]
.FindAll(TreeScope.Children, Condition.TrueCondition)[0]
.FindAll(TreeScope.Children, Condition.TrueCondition)[0]
.FindAll(TreeScope.Children, Condition.TrueCondition)[2]
.FindAll(TreeScope.Children, Condition.TrueCondition)[0];
Unfortunately, when I attempt to edit the value, I am hit with an error message that the selected element is read only. However, the element is in fact not read-only. Also, the element does not have the automationId that it should have. None of the elements in the tree have an AutomationId when viewed with the UIAutomation.
The application that I am attempting to automate is a proprietary application, and this is the first time I've had this issue. I'm not sure what might be causing this, what would be something I could look into?
EDIT: Just as an update, I was able to successfully locate the elements required using indexing from root.FindAll(TreeScope.Descendants, Condition.TrueCondition).
However, I have the following code:
cachedElement = findAll[index];
Console.Write("cachedelement : "); cachedElement.ToConsole();
return 0;
If I just let the program run, it fails when it tries to write the text to the text field. Also, it shows that the selected element has no attributes (during the cachedelement.ToConsole).
Interestingly, if I put a breakpoint on return 0; (or use System.Diagnostics.Debugger.Break()), cachedElement.ToConsole() outputs the LCT as "edit" (still no automationId), and writes the text to the text field properly. Why I find this interesting, is that the breakpoint is set after the call to ToConsole. It shouldn't have an effect on the running code at all.
Based on your second code example the element you are looking for is nested pretty far down the tree so the first code example will never find the element because it is only looking at children of the desktop. If you want to look for the element from the root node you would need to use TreeScope.Descendants for the treescope. I don't recommend using descendants though because it will be slow and more than likely it will cause a stack overflow when used from the root element.
In the worst case scenario I do a FindFirst for my window using child scope from the root element then I use descendants from the applications root. This only works quickly though on small applications with trivial users interfaces. If you have something complex like a grid with cells I would suggest using FindFirst with child scope all the way down to the element you are looking for similar to how you used the find all.
If you can post the code you are using to edit the element I can update this answer with information on how to edit the control that is specific to your situation. In general though how you would edit a text box control would be to use the ValuePattern like this.
public void SetValue(AutomationElement element, string text)
{
var valuePattern = (ValuePattern) element.GetCurrentPattern(ValuePattern.Pattern);
valuePattern.SetValue(text);
}
Hopefully this helps.

Complications with Selenium's GetAttribute method

I recently attempted to use selenium RC's GetAttribute method but immediately ran into a challenge. I tried to execute a very simple selenium.GetAttribute("//a/#href") but the code threw a SeleniumException with the message "ERROR: Could not find element attribute: //a/#href".
By substituting selenium.GetText("//a[#href]") in place of the GetAttribute call, I confirmed that an element was definitely present, as this statement properly returned the text of the link.
I then tried:
pointing to a different web page with a different protocol (file:/// vs http://) -- same problem.
using a different xpath locator pointing to a different attribute -- same problem.
using a DOM locator selenium.GetAttribute("document.getElementsByTagName('a')[0].getAttribute('href')") -- same problem; slightly different error message (and the error message is missing the final parenthesis): "ERROR: Element document.getElementsByTagName('a')[0].getAttribute('href' not found". Note that this exact expression works correctly in Firebug's console.
using absolute instead of relative xpath addressing, with selenium.GetText("xpath=/html/body/a[#href]") to confirm the existence and then selenium.GetAttribute("xpath=/html/body/a/#href") to get the attribute -- and it worked!
While the manual clearly states that relative xpath locators do not need an explicit locator type (i.e. the "xpath=" prefix) it is silent about absolute xpath locators; I interpret from this that the prefix is required. But out of curiousity, I went back to my relative expression and added the explicit prefix--changing selenium.GetAttribute("//a/#href") to selenium.GetAttribute("xpath=//a/#href") -- and this also worked!
Finally, my experiments with the very handy Find button in Selenium IDE show that it does fine with elements but fails with attributes. I can understand that it is not meaningful to highlight an attribute since attributes are not visible page elements, but why not highlight the element containing the attribute, and make it in a different color? Perhaps not a trivial task...
My questions:
I distilled the results of the above experiments down to these questions; this is the whole purpose of my posting here! Each of these seems like a bug to me but let me know if you think my usage is incorrect or there is a workaround:
Why does GetAttribute with an XPath locator type uniquely require an explicit locator type when other methods (e.g. GetText) do not?
Why did the DOM locator fail with a 'not found' error? (The manual also clearly states that DOM locators do not require an explicit locator type prefix, but I nevertheless tried adding "dom=" as a prefix on the DOM test; it still failed.)
Why does Selenium IDE not fail more gracefully when attempting to highlight (Find) an attribute? With the same "xpath=//a/#href" locator, pressing the Find button yields this ugly message: "[error] locator not found: xpath=//a/#href, error = [Exception... "Could not convert JavaScript argument arg 0 [inIFlasher.scrollElementIntoView]" nsresult: "0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)" location: "JS frame :: chrome://selenium-ide/content/selenium-runner.js :: showElement :: line 386" data: no]"
Your input is also requested for the following: The pattern I wanted for each test here was (A) GetText(locator-for-element-with-attribute) to confirm the presence of the element then (B) GetAttribute(locator-for-attribute-itself). Of the 6 slots in the table below I solved 3 of them successfully as just detailed, and a 4th seems to be a bug. Are there solutions for the remaining two slots?
Type GetText GetAttribute
XPath //a[#href] xpath=//a/#href
CSS css=a[href] ??
DOM ?? document.getElementsByTagName('a')[0].getAttribute('href')
(Details: Selenium RC version 1.0.3, Browser: Firefox 3.6.13, My target code in C#)
Selenium RC's GetAttribute method returns the value of the element\attribute locator. The general form for these locators is
"[locator (id, xpath, css, etc)]#[attribute name]"
for example
"SaveButton#href"
returns the value of the href attribute on the element with the id SaveButton. Xpath locators can also be used:
"xpath=//a[contains(#id, 'SaveButton')]#href"
returns the value of the href attribute on the element whose id contains the text SaveButton.
To answer your questions,
1: I don't really know, this is a question for the designers of Selenium.
2: The Selenium commands execute several different "contexts". In some of the commands, document refers to the web page under test, in other commands, document refers to the page containing the Selenium frame (testRunner.html I believe).
3: The error message says that it cannot find the element you requested. The information after that could be useful to the Selenium team if there is actually a bug present, but doesn't really affect you. The more information the better, right?
http://release.seleniumhq.org/selenium-remote-control/0.9.2/doc/java/com/thoughtworks/selenium/Selenium.html#getAttribute%28java.lang.String%29
getAttribute
java.lang.String getAttribute(java.lang.String attributeLocator)
Gets the value of an element attribute.
Parameters:
attributeLocator - an element locator followed by an # sign and then the name of the attribute, e.g. "foo#bar"
Returns:
the value of the specified attribute
So you should say selenium.GetAttribute("locator#href") Locator being id or name. If your a element does not have id or name, you should use xpath, selenium.GetAttribute("xpath=/html/body/a/#href") like you already successfully tried.

Categories

Resources